1193645Ssimon/* fips_dsa_sign.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296465Sdelphij * 2007. 5193645Ssimon */ 6193645Ssimon/* ==================================================================== 7193645Ssimon * Copyright (c) 2007 The OpenSSL Project. All rights reserved. 8193645Ssimon * 9193645Ssimon * Redistribution and use in source and binary forms, with or without 10193645Ssimon * modification, are permitted provided that the following conditions 11193645Ssimon * are met: 12193645Ssimon * 13193645Ssimon * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15193645Ssimon * 16193645Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17193645Ssimon * notice, this list of conditions and the following disclaimer in 18193645Ssimon * the documentation and/or other materials provided with the 19193645Ssimon * distribution. 20193645Ssimon * 21193645Ssimon * 3. All advertising materials mentioning features or use of this 22193645Ssimon * software must display the following acknowledgment: 23193645Ssimon * "This product includes software developed by the OpenSSL Project 24193645Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25193645Ssimon * 26193645Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27193645Ssimon * endorse or promote products derived from this software without 28193645Ssimon * prior written permission. For written permission, please contact 29193645Ssimon * licensing@OpenSSL.org. 30193645Ssimon * 31193645Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32193645Ssimon * nor may "OpenSSL" appear in their names without prior written 33193645Ssimon * permission of the OpenSSL Project. 34193645Ssimon * 35193645Ssimon * 6. Redistributions of any form whatsoever must retain the following 36193645Ssimon * acknowledgment: 37193645Ssimon * "This product includes software developed by the OpenSSL Project 38193645Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39193645Ssimon * 40193645Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41193645Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42193645Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43193645Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44193645Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45193645Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46193645Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47193645Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48193645Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49193645Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50193645Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51193645Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52193645Ssimon * ==================================================================== 53193645Ssimon * 54193645Ssimon * This product includes cryptographic software written by Eric Young 55193645Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 56193645Ssimon * Hudson (tjh@cryptsoft.com). 57193645Ssimon * 58193645Ssimon */ 59193645Ssimon 60193645Ssimon#include <string.h> 61193645Ssimon#include <openssl/evp.h> 62193645Ssimon#include <openssl/dsa.h> 63193645Ssimon#include <openssl/err.h> 64193645Ssimon#include <openssl/sha.h> 65193645Ssimon#include <openssl/bn.h> 66193645Ssimon 67193645Ssimon#ifdef OPENSSL_FIPS 68193645Ssimon 69296465Sdelphij/* 70296465Sdelphij * FIPS versions of DSA_sign() and DSA_verify(). These include a tiny ASN1 71296465Sdelphij * encoder/decoder to handle the specific case of a DSA signature. 72193645Ssimon */ 73193645Ssimon 74296465Sdelphij# if 0 75193645Ssimonint FIPS_dsa_size(DSA *r) 76296465Sdelphij{ 77296465Sdelphij int ilen; 78296465Sdelphij ilen = BN_num_bytes(r->q); 79296465Sdelphij if (ilen > 20) 80296465Sdelphij return -1; 81296465Sdelphij /* If MSB set need padding byte */ 82296465Sdelphij ilen++; 83296465Sdelphij /* 84296465Sdelphij * Also need 2 bytes INTEGER header for r and s plus 2 bytes SEQUENCE 85296465Sdelphij * header making 6 in total. 86296465Sdelphij */ 87296465Sdelphij return ilen * 2 + 6; 88296465Sdelphij} 89296465Sdelphij# endif 90193645Ssimon 91296465Sdelphij/* 92296465Sdelphij * Tiny ASN1 encoder for DSA_SIG structure. We can assume r, s smaller than 93193645Ssimon * 0x80 octets as by the DSA standards they will be less than 2^160 94193645Ssimon */ 95193645Ssimon 96193645Ssimonint FIPS_dsa_sig_encode(unsigned char *out, DSA_SIG *sig) 97296465Sdelphij{ 98296465Sdelphij int rlen, slen, rpad, spad, seqlen; 99296465Sdelphij rlen = BN_num_bytes(sig->r); 100296465Sdelphij if (rlen > 20) 101296465Sdelphij return -1; 102296465Sdelphij if (BN_num_bits(sig->r) & 0x7) 103296465Sdelphij rpad = 0; 104296465Sdelphij else 105296465Sdelphij rpad = 1; 106296465Sdelphij slen = BN_num_bytes(sig->s); 107296465Sdelphij if (slen > 20) 108296465Sdelphij return -1; 109296465Sdelphij if (BN_num_bits(sig->s) & 0x7) 110296465Sdelphij spad = 0; 111296465Sdelphij else 112296465Sdelphij spad = 1; 113296465Sdelphij /* Length of SEQUENCE, (1 tag + 1 len octet) * 2 + content octets */ 114296465Sdelphij seqlen = rlen + rpad + slen + spad + 4; 115296465Sdelphij /* Actual encoded length: include SEQUENCE header */ 116296465Sdelphij if (!out) 117296465Sdelphij return seqlen + 2; 118193645Ssimon 119296465Sdelphij /* Output SEQUENCE header */ 120296465Sdelphij *out++ = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; 121296465Sdelphij *out++ = (unsigned char)seqlen; 122193645Ssimon 123296465Sdelphij /* Output r */ 124296465Sdelphij *out++ = V_ASN1_INTEGER; 125296465Sdelphij *out++ = (unsigned char)(rlen + rpad); 126296465Sdelphij if (rpad) 127296465Sdelphij *out++ = 0; 128296465Sdelphij BN_bn2bin(sig->r, out); 129296465Sdelphij out += rlen; 130193645Ssimon 131296465Sdelphij /* Output s */ 132296465Sdelphij *out++ = V_ASN1_INTEGER; 133296465Sdelphij *out++ = (unsigned char)(slen + spad); 134296465Sdelphij if (spad) 135296465Sdelphij *out++ = 0; 136296465Sdelphij BN_bn2bin(sig->s, out); 137296465Sdelphij return seqlen + 2; 138296465Sdelphij} 139193645Ssimon 140193645Ssimon/* Companion DSA_SIG decoder */ 141193645Ssimon 142193645Ssimonint FIPS_dsa_sig_decode(DSA_SIG *sig, const unsigned char *in, int inlen) 143296465Sdelphij{ 144296465Sdelphij int seqlen, rlen, slen; 145296465Sdelphij const unsigned char *rbin; 146296465Sdelphij /* Sanity check */ 147193645Ssimon 148296465Sdelphij /* Need SEQUENCE tag */ 149296465Sdelphij if (*in++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) 150296465Sdelphij return 0; 151296465Sdelphij /* Get length octet */ 152296465Sdelphij seqlen = *in++; 153296465Sdelphij /* Check sensible length value */ 154296465Sdelphij if (seqlen < 4 || seqlen > 0x7F) 155296465Sdelphij return 0; 156296465Sdelphij /* Check INTEGER tag */ 157296465Sdelphij if (*in++ != V_ASN1_INTEGER) 158296465Sdelphij return 0; 159296465Sdelphij rlen = *in++; 160296465Sdelphij seqlen -= 2 + rlen; 161296465Sdelphij /* Check sensible seqlen value */ 162296465Sdelphij if (seqlen < 2) 163296465Sdelphij return 0; 164296465Sdelphij rbin = in; 165296465Sdelphij in += rlen; 166296465Sdelphij /* Check INTEGER tag */ 167296465Sdelphij if (*in++ != V_ASN1_INTEGER) 168296465Sdelphij return 0; 169296465Sdelphij slen = *in++; 170296465Sdelphij /* 171296465Sdelphij * Remaining bytes of SEQUENCE should exactly match encoding of s 172296465Sdelphij */ 173296465Sdelphij if (seqlen != (slen + 2)) 174296465Sdelphij return 0; 175296465Sdelphij if (!sig->r && !(sig->r = BN_new())) 176296465Sdelphij return 0; 177296465Sdelphij if (!sig->s && !(sig->s = BN_new())) 178296465Sdelphij return 0; 179296465Sdelphij if (!BN_bin2bn(rbin, rlen, sig->r)) 180296465Sdelphij return 0; 181296465Sdelphij if (!BN_bin2bn(in, slen, sig->s)) 182296465Sdelphij return 0; 183296465Sdelphij return 1; 184296465Sdelphij} 185193645Ssimon 186193645Ssimonstatic int fips_dsa_sign(int type, const unsigned char *x, int y, 187296465Sdelphij unsigned char *sig, unsigned int *siglen, 188296465Sdelphij EVP_MD_SVCTX * sv) 189296465Sdelphij{ 190296465Sdelphij DSA *dsa = sv->key; 191296465Sdelphij unsigned char dig[EVP_MAX_MD_SIZE]; 192296465Sdelphij unsigned int dlen; 193296465Sdelphij DSA_SIG *s; 194296465Sdelphij EVP_DigestFinal_ex(sv->mctx, dig, &dlen); 195296465Sdelphij s = dsa->meth->dsa_do_sign(dig, dlen, dsa); 196296465Sdelphij OPENSSL_cleanse(dig, dlen); 197296465Sdelphij if (s == NULL) { 198296465Sdelphij *siglen = 0; 199296465Sdelphij return 0; 200296465Sdelphij } 201296465Sdelphij *siglen = FIPS_dsa_sig_encode(sig, s); 202296465Sdelphij DSA_SIG_free(s); 203296465Sdelphij if (*siglen < 0) 204296465Sdelphij return 0; 205296465Sdelphij return 1; 206296465Sdelphij} 207193645Ssimon 208193645Ssimonstatic int fips_dsa_verify(int type, const unsigned char *x, int y, 209296465Sdelphij const unsigned char *sigbuf, unsigned int siglen, 210296465Sdelphij EVP_MD_SVCTX * sv) 211296465Sdelphij{ 212296465Sdelphij DSA *dsa = sv->key; 213296465Sdelphij DSA_SIG *s; 214296465Sdelphij int ret = -1; 215296465Sdelphij unsigned char dig[EVP_MAX_MD_SIZE]; 216296465Sdelphij unsigned int dlen; 217193645Ssimon 218296465Sdelphij s = DSA_SIG_new(); 219296465Sdelphij if (s == NULL) 220296465Sdelphij return ret; 221296465Sdelphij if (!FIPS_dsa_sig_decode(s, sigbuf, siglen)) 222296465Sdelphij goto err; 223296465Sdelphij EVP_DigestFinal_ex(sv->mctx, dig, &dlen); 224296465Sdelphij ret = dsa->meth->dsa_do_verify(dig, dlen, s, dsa); 225296465Sdelphij OPENSSL_cleanse(dig, dlen); 226296465Sdelphij err: 227296465Sdelphij DSA_SIG_free(s); 228296465Sdelphij return ret; 229296465Sdelphij} 230193645Ssimon 231193645Ssimonstatic int init(EVP_MD_CTX *ctx) 232296465Sdelphij{ 233296465Sdelphij return SHA1_Init(ctx->md_data); 234296465Sdelphij} 235193645Ssimon 236296465Sdelphijstatic int update(EVP_MD_CTX *ctx, const void *data, size_t count) 237296465Sdelphij{ 238296465Sdelphij return SHA1_Update(ctx->md_data, data, count); 239296465Sdelphij} 240193645Ssimon 241296465Sdelphijstatic int final(EVP_MD_CTX *ctx, unsigned char *md) 242296465Sdelphij{ 243296465Sdelphij return SHA1_Final(md, ctx->md_data); 244296465Sdelphij} 245193645Ssimon 246296465Sdelphijstatic const EVP_MD dss1_md = { 247296465Sdelphij NID_dsa, 248296465Sdelphij NID_dsaWithSHA1, 249296465Sdelphij SHA_DIGEST_LENGTH, 250296465Sdelphij EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX, 251296465Sdelphij init, 252296465Sdelphij update, 253296465Sdelphij final, 254296465Sdelphij NULL, 255296465Sdelphij NULL, 256296465Sdelphij (evp_sign_method *) fips_dsa_sign, 257296465Sdelphij (evp_verify_method *) fips_dsa_verify, 258296465Sdelphij {EVP_PKEY_DSA, EVP_PKEY_DSA2, EVP_PKEY_DSA3, EVP_PKEY_DSA4, 0}, 259296465Sdelphij SHA_CBLOCK, 260296465Sdelphij sizeof(EVP_MD *) + sizeof(SHA_CTX), 261296465Sdelphij}; 262193645Ssimon 263193645Ssimonconst EVP_MD *EVP_dss1(void) 264296465Sdelphij{ 265296465Sdelphij return (&dss1_md); 266296465Sdelphij} 267193645Ssimon#endif 268