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