fips_dsa_sign.c revision 296465
1/* fips_dsa_sign.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 2007. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2007 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <string.h> 61#include <openssl/evp.h> 62#include <openssl/dsa.h> 63#include <openssl/err.h> 64#include <openssl/sha.h> 65#include <openssl/bn.h> 66 67#ifdef OPENSSL_FIPS 68 69/* 70 * FIPS versions of DSA_sign() and DSA_verify(). These include a tiny ASN1 71 * encoder/decoder to handle the specific case of a DSA signature. 72 */ 73 74# if 0 75int FIPS_dsa_size(DSA *r) 76{ 77 int ilen; 78 ilen = BN_num_bytes(r->q); 79 if (ilen > 20) 80 return -1; 81 /* If MSB set need padding byte */ 82 ilen++; 83 /* 84 * Also need 2 bytes INTEGER header for r and s plus 2 bytes SEQUENCE 85 * header making 6 in total. 86 */ 87 return ilen * 2 + 6; 88} 89# endif 90 91/* 92 * Tiny ASN1 encoder for DSA_SIG structure. We can assume r, s smaller than 93 * 0x80 octets as by the DSA standards they will be less than 2^160 94 */ 95 96int FIPS_dsa_sig_encode(unsigned char *out, DSA_SIG *sig) 97{ 98 int rlen, slen, rpad, spad, seqlen; 99 rlen = BN_num_bytes(sig->r); 100 if (rlen > 20) 101 return -1; 102 if (BN_num_bits(sig->r) & 0x7) 103 rpad = 0; 104 else 105 rpad = 1; 106 slen = BN_num_bytes(sig->s); 107 if (slen > 20) 108 return -1; 109 if (BN_num_bits(sig->s) & 0x7) 110 spad = 0; 111 else 112 spad = 1; 113 /* Length of SEQUENCE, (1 tag + 1 len octet) * 2 + content octets */ 114 seqlen = rlen + rpad + slen + spad + 4; 115 /* Actual encoded length: include SEQUENCE header */ 116 if (!out) 117 return seqlen + 2; 118 119 /* Output SEQUENCE header */ 120 *out++ = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; 121 *out++ = (unsigned char)seqlen; 122 123 /* Output r */ 124 *out++ = V_ASN1_INTEGER; 125 *out++ = (unsigned char)(rlen + rpad); 126 if (rpad) 127 *out++ = 0; 128 BN_bn2bin(sig->r, out); 129 out += rlen; 130 131 /* Output s */ 132 *out++ = V_ASN1_INTEGER; 133 *out++ = (unsigned char)(slen + spad); 134 if (spad) 135 *out++ = 0; 136 BN_bn2bin(sig->s, out); 137 return seqlen + 2; 138} 139 140/* Companion DSA_SIG decoder */ 141 142int FIPS_dsa_sig_decode(DSA_SIG *sig, const unsigned char *in, int inlen) 143{ 144 int seqlen, rlen, slen; 145 const unsigned char *rbin; 146 /* Sanity check */ 147 148 /* Need SEQUENCE tag */ 149 if (*in++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) 150 return 0; 151 /* Get length octet */ 152 seqlen = *in++; 153 /* Check sensible length value */ 154 if (seqlen < 4 || seqlen > 0x7F) 155 return 0; 156 /* Check INTEGER tag */ 157 if (*in++ != V_ASN1_INTEGER) 158 return 0; 159 rlen = *in++; 160 seqlen -= 2 + rlen; 161 /* Check sensible seqlen value */ 162 if (seqlen < 2) 163 return 0; 164 rbin = in; 165 in += rlen; 166 /* Check INTEGER tag */ 167 if (*in++ != V_ASN1_INTEGER) 168 return 0; 169 slen = *in++; 170 /* 171 * Remaining bytes of SEQUENCE should exactly match encoding of s 172 */ 173 if (seqlen != (slen + 2)) 174 return 0; 175 if (!sig->r && !(sig->r = BN_new())) 176 return 0; 177 if (!sig->s && !(sig->s = BN_new())) 178 return 0; 179 if (!BN_bin2bn(rbin, rlen, sig->r)) 180 return 0; 181 if (!BN_bin2bn(in, slen, sig->s)) 182 return 0; 183 return 1; 184} 185 186static int fips_dsa_sign(int type, const unsigned char *x, int y, 187 unsigned char *sig, unsigned int *siglen, 188 EVP_MD_SVCTX * sv) 189{ 190 DSA *dsa = sv->key; 191 unsigned char dig[EVP_MAX_MD_SIZE]; 192 unsigned int dlen; 193 DSA_SIG *s; 194 EVP_DigestFinal_ex(sv->mctx, dig, &dlen); 195 s = dsa->meth->dsa_do_sign(dig, dlen, dsa); 196 OPENSSL_cleanse(dig, dlen); 197 if (s == NULL) { 198 *siglen = 0; 199 return 0; 200 } 201 *siglen = FIPS_dsa_sig_encode(sig, s); 202 DSA_SIG_free(s); 203 if (*siglen < 0) 204 return 0; 205 return 1; 206} 207 208static int fips_dsa_verify(int type, const unsigned char *x, int y, 209 const unsigned char *sigbuf, unsigned int siglen, 210 EVP_MD_SVCTX * sv) 211{ 212 DSA *dsa = sv->key; 213 DSA_SIG *s; 214 int ret = -1; 215 unsigned char dig[EVP_MAX_MD_SIZE]; 216 unsigned int dlen; 217 218 s = DSA_SIG_new(); 219 if (s == NULL) 220 return ret; 221 if (!FIPS_dsa_sig_decode(s, sigbuf, siglen)) 222 goto err; 223 EVP_DigestFinal_ex(sv->mctx, dig, &dlen); 224 ret = dsa->meth->dsa_do_verify(dig, dlen, s, dsa); 225 OPENSSL_cleanse(dig, dlen); 226 err: 227 DSA_SIG_free(s); 228 return ret; 229} 230 231static int init(EVP_MD_CTX *ctx) 232{ 233 return SHA1_Init(ctx->md_data); 234} 235 236static int update(EVP_MD_CTX *ctx, const void *data, size_t count) 237{ 238 return SHA1_Update(ctx->md_data, data, count); 239} 240 241static int final(EVP_MD_CTX *ctx, unsigned char *md) 242{ 243 return SHA1_Final(md, ctx->md_data); 244} 245 246static const EVP_MD dss1_md = { 247 NID_dsa, 248 NID_dsaWithSHA1, 249 SHA_DIGEST_LENGTH, 250 EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX, 251 init, 252 update, 253 final, 254 NULL, 255 NULL, 256 (evp_sign_method *) fips_dsa_sign, 257 (evp_verify_method *) fips_dsa_verify, 258 {EVP_PKEY_DSA, EVP_PKEY_DSA2, EVP_PKEY_DSA3, EVP_PKEY_DSA4, 0}, 259 SHA_CBLOCK, 260 sizeof(EVP_MD *) + sizeof(SHA_CTX), 261}; 262 263const EVP_MD *EVP_dss1(void) 264{ 265 return (&dss1_md); 266} 267#endif 268