155714Skris/* crypto/asn1/a_sign.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280297Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280297Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280297Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280297Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280297Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280297Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
58100928Snectar/* ====================================================================
59160814Ssimon * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
60100928Snectar *
61100928Snectar * Redistribution and use in source and binary forms, with or without
62100928Snectar * modification, are permitted provided that the following conditions
63100928Snectar * are met:
64100928Snectar *
65100928Snectar * 1. Redistributions of source code must retain the above copyright
66280297Sjkim *    notice, this list of conditions and the following disclaimer.
67100928Snectar *
68100928Snectar * 2. Redistributions in binary form must reproduce the above copyright
69100928Snectar *    notice, this list of conditions and the following disclaimer in
70100928Snectar *    the documentation and/or other materials provided with the
71100928Snectar *    distribution.
72100928Snectar *
73100928Snectar * 3. All advertising materials mentioning features or use of this
74100928Snectar *    software must display the following acknowledgment:
75100928Snectar *    "This product includes software developed by the OpenSSL Project
76100928Snectar *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77100928Snectar *
78100928Snectar * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79100928Snectar *    endorse or promote products derived from this software without
80100928Snectar *    prior written permission. For written permission, please contact
81100928Snectar *    openssl-core@openssl.org.
82100928Snectar *
83100928Snectar * 5. Products derived from this software may not be called "OpenSSL"
84100928Snectar *    nor may "OpenSSL" appear in their names without prior written
85100928Snectar *    permission of the OpenSSL Project.
86100928Snectar *
87100928Snectar * 6. Redistributions of any form whatsoever must retain the following
88100928Snectar *    acknowledgment:
89100928Snectar *    "This product includes software developed by the OpenSSL Project
90100928Snectar *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91100928Snectar *
92100928Snectar * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93100928Snectar * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94100928Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95100928Snectar * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96100928Snectar * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97100928Snectar * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98100928Snectar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99100928Snectar * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100100928Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101100928Snectar * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102100928Snectar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103100928Snectar * OF THE POSSIBILITY OF SUCH DAMAGE.
104100928Snectar * ====================================================================
105100928Snectar *
106100928Snectar * This product includes cryptographic software written by Eric Young
107100928Snectar * (eay@cryptsoft.com).  This product includes software written by Tim
108100928Snectar * Hudson (tjh@cryptsoft.com).
109100928Snectar *
110100928Snectar */
11155714Skris
11255714Skris#include <stdio.h>
11355714Skris#include <time.h>
11455714Skris
11555714Skris#include "cryptlib.h"
11659191Skris
11759191Skris#ifndef NO_SYS_TYPES_H
11859191Skris# include <sys/types.h>
11959191Skris#endif
12059191Skris
12155714Skris#include <openssl/bn.h>
12255714Skris#include <openssl/evp.h>
12355714Skris#include <openssl/x509.h>
12455714Skris#include <openssl/objects.h>
12555714Skris#include <openssl/buffer.h>
126238405Sjkim#include "asn1_locl.h"
12755714Skris
128109998Smarkm#ifndef NO_ASN1_OLD
129109998Smarkm
130160814Ssimonint ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
131280297Sjkim              ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
132280297Sjkim              const EVP_MD *type)
133280297Sjkim{
134280297Sjkim    EVP_MD_CTX ctx;
135280297Sjkim    unsigned char *p, *buf_in = NULL, *buf_out = NULL;
136280297Sjkim    int i, inl = 0, outl = 0, outll = 0;
137280297Sjkim    X509_ALGOR *a;
13855714Skris
139280297Sjkim    EVP_MD_CTX_init(&ctx);
140280297Sjkim    for (i = 0; i < 2; i++) {
141280297Sjkim        if (i == 0)
142280297Sjkim            a = algor1;
143280297Sjkim        else
144280297Sjkim            a = algor2;
145280297Sjkim        if (a == NULL)
146280297Sjkim            continue;
147280297Sjkim        if (type->pkey_type == NID_dsaWithSHA1) {
148280297Sjkim            /*
149280297Sjkim             * special case: RFC 2459 tells us to omit 'parameters' with
150280297Sjkim             * id-dsa-with-sha1
151280297Sjkim             */
152280297Sjkim            ASN1_TYPE_free(a->parameter);
153280297Sjkim            a->parameter = NULL;
154280297Sjkim        } else if ((a->parameter == NULL) ||
155280297Sjkim                   (a->parameter->type != V_ASN1_NULL)) {
156280297Sjkim            ASN1_TYPE_free(a->parameter);
157280297Sjkim            if ((a->parameter = ASN1_TYPE_new()) == NULL)
158280297Sjkim                goto err;
159280297Sjkim            a->parameter->type = V_ASN1_NULL;
160280297Sjkim        }
161280297Sjkim        ASN1_OBJECT_free(a->algorithm);
162280297Sjkim        a->algorithm = OBJ_nid2obj(type->pkey_type);
163280297Sjkim        if (a->algorithm == NULL) {
164280297Sjkim            ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE);
165280297Sjkim            goto err;
166280297Sjkim        }
167280297Sjkim        if (a->algorithm->length == 0) {
168280297Sjkim            ASN1err(ASN1_F_ASN1_SIGN,
169280297Sjkim                    ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
170280297Sjkim            goto err;
171280297Sjkim        }
172280297Sjkim    }
173280297Sjkim    inl = i2d(data, NULL);
174280297Sjkim    buf_in = (unsigned char *)OPENSSL_malloc((unsigned int)inl);
175280297Sjkim    outll = outl = EVP_PKEY_size(pkey);
176280297Sjkim    buf_out = (unsigned char *)OPENSSL_malloc((unsigned int)outl);
177280297Sjkim    if ((buf_in == NULL) || (buf_out == NULL)) {
178280297Sjkim        outl = 0;
179280297Sjkim        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
180280297Sjkim        goto err;
181280297Sjkim    }
182280297Sjkim    p = buf_in;
18355714Skris
184280297Sjkim    i2d(data, &p);
185280297Sjkim    if (!EVP_SignInit_ex(&ctx, type, NULL)
186280297Sjkim        || !EVP_SignUpdate(&ctx, (unsigned char *)buf_in, inl)
187280297Sjkim        || !EVP_SignFinal(&ctx, (unsigned char *)buf_out,
188280297Sjkim                          (unsigned int *)&outl, pkey)) {
189280297Sjkim        outl = 0;
190280297Sjkim        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB);
191280297Sjkim        goto err;
192280297Sjkim    }
193280297Sjkim    if (signature->data != NULL)
194280297Sjkim        OPENSSL_free(signature->data);
195280297Sjkim    signature->data = buf_out;
196280297Sjkim    buf_out = NULL;
197280297Sjkim    signature->length = outl;
198280297Sjkim    /*
199280297Sjkim     * In the interests of compatibility, I'll make sure that the bit string
200280297Sjkim     * has a 'not-used bits' value of 0
201280297Sjkim     */
202280297Sjkim    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
203280297Sjkim    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
204280297Sjkim err:
205280297Sjkim    EVP_MD_CTX_cleanup(&ctx);
206280297Sjkim    if (buf_in != NULL) {
207280297Sjkim        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
208280297Sjkim        OPENSSL_free(buf_in);
209280297Sjkim    }
210280297Sjkim    if (buf_out != NULL) {
211280297Sjkim        OPENSSL_cleanse((char *)buf_out, outll);
212280297Sjkim        OPENSSL_free(buf_out);
213280297Sjkim    }
214280297Sjkim    return (outl);
215280297Sjkim}
216109998Smarkm
217109998Smarkm#endif
218109998Smarkm
219280297Sjkimint ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
220280297Sjkim                   X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
221280297Sjkim                   EVP_PKEY *pkey, const EVP_MD *type)
222280297Sjkim{
223280297Sjkim    EVP_MD_CTX ctx;
224280297Sjkim    EVP_MD_CTX_init(&ctx);
225280297Sjkim    if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
226280297Sjkim        EVP_MD_CTX_cleanup(&ctx);
227280297Sjkim        return 0;
228280297Sjkim    }
229280297Sjkim    return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
230280297Sjkim}
231238405Sjkim
232238405Sjkimint ASN1_item_sign_ctx(const ASN1_ITEM *it,
233280297Sjkim                       X509_ALGOR *algor1, X509_ALGOR *algor2,
234280297Sjkim                       ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
235280297Sjkim{
236280297Sjkim    const EVP_MD *type;
237280297Sjkim    EVP_PKEY *pkey;
238280297Sjkim    unsigned char *buf_in = NULL, *buf_out = NULL;
239280297Sjkim    size_t inl = 0, outl = 0, outll = 0;
240280297Sjkim    int signid, paramtype;
241280297Sjkim    int rv;
242109998Smarkm
243280297Sjkim    type = EVP_MD_CTX_md(ctx);
244280297Sjkim    pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
245238405Sjkim
246280297Sjkim    if (!type || !pkey) {
247280297Sjkim        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
248280297Sjkim        return 0;
249280297Sjkim    }
250238405Sjkim
251280297Sjkim    if (pkey->ameth->item_sign) {
252280297Sjkim        rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature);
253280297Sjkim        if (rv == 1)
254280297Sjkim            outl = signature->length;
255280297Sjkim        /*-
256280297Sjkim         * Return value meanings:
257280297Sjkim         * <=0: error.
258280297Sjkim         *   1: method does everything.
259280297Sjkim         *   2: carry on as normal.
260280297Sjkim         *   3: ASN1 method sets algorithm identifiers: just sign.
261280297Sjkim         */
262280297Sjkim        if (rv <= 0)
263280297Sjkim            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
264280297Sjkim        if (rv <= 1)
265280297Sjkim            goto err;
266280297Sjkim    } else
267280297Sjkim        rv = 2;
268238405Sjkim
269280297Sjkim    if (rv == 2) {
270280297Sjkim        if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
271280297Sjkim            if (!pkey->ameth ||
272280297Sjkim                !OBJ_find_sigid_by_algs(&signid,
273280297Sjkim                                        EVP_MD_nid(type),
274280297Sjkim                                        pkey->ameth->pkey_id)) {
275280297Sjkim                ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
276280297Sjkim                        ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
277280297Sjkim                return 0;
278280297Sjkim            }
279280297Sjkim        } else
280280297Sjkim            signid = type->pkey_type;
281238405Sjkim
282280297Sjkim        if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
283280297Sjkim            paramtype = V_ASN1_NULL;
284280297Sjkim        else
285280297Sjkim            paramtype = V_ASN1_UNDEF;
286238405Sjkim
287280297Sjkim        if (algor1)
288280297Sjkim            X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
289280297Sjkim        if (algor2)
290280297Sjkim            X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
291238405Sjkim
292280297Sjkim    }
293238405Sjkim
294280297Sjkim    inl = ASN1_item_i2d(asn, &buf_in, it);
295280297Sjkim    outll = outl = EVP_PKEY_size(pkey);
296280297Sjkim    buf_out = OPENSSL_malloc((unsigned int)outl);
297280297Sjkim    if ((buf_in == NULL) || (buf_out == NULL)) {
298280297Sjkim        outl = 0;
299280297Sjkim        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
300280297Sjkim        goto err;
301280297Sjkim    }
302109998Smarkm
303280297Sjkim    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
304280297Sjkim        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
305280297Sjkim        outl = 0;
306280297Sjkim        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
307280297Sjkim        goto err;
308280297Sjkim    }
309280297Sjkim    if (signature->data != NULL)
310280297Sjkim        OPENSSL_free(signature->data);
311280297Sjkim    signature->data = buf_out;
312280297Sjkim    buf_out = NULL;
313280297Sjkim    signature->length = outl;
314280297Sjkim    /*
315280297Sjkim     * In the interests of compatibility, I'll make sure that the bit string
316280297Sjkim     * has a 'not-used bits' value of 0
317280297Sjkim     */
318280297Sjkim    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
319280297Sjkim    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
320280297Sjkim err:
321280297Sjkim    EVP_MD_CTX_cleanup(ctx);
322280297Sjkim    if (buf_in != NULL) {
323280297Sjkim        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
324280297Sjkim        OPENSSL_free(buf_in);
325280297Sjkim    }
326280297Sjkim    if (buf_out != NULL) {
327280297Sjkim        OPENSSL_cleanse((char *)buf_out, outll);
328280297Sjkim        OPENSSL_free(buf_out);
329280297Sjkim    }
330280297Sjkim    return (outl);
331280297Sjkim}
332