155714Skris/* crypto/asn1/a_verify.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.
8296341Sdelphij *
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).
15296341Sdelphij *
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.
22296341Sdelphij *
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 :-).
37296341Sdelphij * 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)"
40296341Sdelphij *
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.
52296341Sdelphij *
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 */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <time.h>
6155714Skris
6255714Skris#include "cryptlib.h"
63238405Sjkim#include "asn1_locl.h"
6459191Skris
6559191Skris#ifndef NO_SYS_TYPES_H
6659191Skris# include <sys/types.h>
6759191Skris#endif
6859191Skris
6955714Skris#include <openssl/bn.h>
7055714Skris#include <openssl/x509.h>
7155714Skris#include <openssl/objects.h>
7255714Skris#include <openssl/buffer.h>
7355714Skris#include <openssl/evp.h>
7455714Skris
75109998Smarkm#ifndef NO_ASN1_OLD
76109998Smarkm
77160814Ssimonint ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
78296341Sdelphij                char *data, EVP_PKEY *pkey)
79296341Sdelphij{
80296341Sdelphij    EVP_MD_CTX ctx;
81296341Sdelphij    const EVP_MD *type;
82296341Sdelphij    unsigned char *p, *buf_in = NULL;
83296341Sdelphij    int ret = -1, i, inl;
8455714Skris
85296341Sdelphij    EVP_MD_CTX_init(&ctx);
86296341Sdelphij    i = OBJ_obj2nid(a->algorithm);
87296341Sdelphij    type = EVP_get_digestbyname(OBJ_nid2sn(i));
88296341Sdelphij    if (type == NULL) {
89296341Sdelphij        ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
90296341Sdelphij        goto err;
91296341Sdelphij    }
92277195Sdelphij
93296341Sdelphij    if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
94296341Sdelphij        ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
95296341Sdelphij        goto err;
96296341Sdelphij    }
9755714Skris
98296341Sdelphij    inl = i2d(data, NULL);
99296341Sdelphij    buf_in = OPENSSL_malloc((unsigned int)inl);
100296341Sdelphij    if (buf_in == NULL) {
101296341Sdelphij        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
102296341Sdelphij        goto err;
103296341Sdelphij    }
104296341Sdelphij    p = buf_in;
10555714Skris
106296341Sdelphij    i2d(data, &p);
107296341Sdelphij    if (!EVP_VerifyInit_ex(&ctx, type, NULL)
108296341Sdelphij        || !EVP_VerifyUpdate(&ctx, (unsigned char *)buf_in, inl)) {
109296341Sdelphij        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
110296341Sdelphij        ret = 0;
111296341Sdelphij        goto err;
112296341Sdelphij    }
11355714Skris
114296341Sdelphij    OPENSSL_cleanse(buf_in, (unsigned int)inl);
115296341Sdelphij    OPENSSL_free(buf_in);
116109998Smarkm
117296341Sdelphij    if (EVP_VerifyFinal(&ctx, (unsigned char *)signature->data,
118296341Sdelphij                        (unsigned int)signature->length, pkey) <= 0) {
119296341Sdelphij        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
120296341Sdelphij        ret = 0;
121296341Sdelphij        goto err;
122296341Sdelphij    }
123296341Sdelphij    /*
124296341Sdelphij     * we don't need to zero the 'ctx' because we just checked public
125296341Sdelphij     * information
126296341Sdelphij     */
127296341Sdelphij    /* memset(&ctx,0,sizeof(ctx)); */
128296341Sdelphij    ret = 1;
129296341Sdelphij err:
130296341Sdelphij    EVP_MD_CTX_cleanup(&ctx);
131296341Sdelphij    return (ret);
132296341Sdelphij}
133296341Sdelphij
134109998Smarkm#endif
135109998Smarkm
136238405Sjkimint ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
137296341Sdelphij                     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
138296341Sdelphij{
139296341Sdelphij    EVP_MD_CTX ctx;
140296341Sdelphij    unsigned char *buf_in = NULL;
141296341Sdelphij    int ret = -1, inl;
142109998Smarkm
143296341Sdelphij    int mdnid, pknid;
144238405Sjkim
145296341Sdelphij    if (!pkey) {
146296341Sdelphij        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
147296341Sdelphij        return -1;
148296341Sdelphij    }
149246772Sjkim
150296341Sdelphij    if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
151296341Sdelphij        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
152296341Sdelphij        return -1;
153296341Sdelphij    }
154277195Sdelphij
155296341Sdelphij    EVP_MD_CTX_init(&ctx);
156238405Sjkim
157296341Sdelphij    /* Convert signature OID into digest and public key OIDs */
158296341Sdelphij    if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
159296341Sdelphij        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
160296341Sdelphij        goto err;
161296341Sdelphij    }
162296341Sdelphij    if (mdnid == NID_undef) {
163296341Sdelphij        if (!pkey->ameth || !pkey->ameth->item_verify) {
164296341Sdelphij            ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
165296341Sdelphij                    ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
166296341Sdelphij            goto err;
167296341Sdelphij        }
168296341Sdelphij        ret = pkey->ameth->item_verify(&ctx, it, asn, a, signature, pkey);
169296341Sdelphij        /*
170296341Sdelphij         * Return value of 2 means carry on, anything else means we exit
171296341Sdelphij         * straight away: either a fatal error of the underlying verification
172296341Sdelphij         * routine handles all verification.
173296341Sdelphij         */
174296341Sdelphij        if (ret != 2)
175296341Sdelphij            goto err;
176296341Sdelphij        ret = -1;
177296341Sdelphij    } else {
178296341Sdelphij        const EVP_MD *type;
179296341Sdelphij        type = EVP_get_digestbynid(mdnid);
180296341Sdelphij        if (type == NULL) {
181296341Sdelphij            ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
182296341Sdelphij                    ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
183296341Sdelphij            goto err;
184296341Sdelphij        }
185160814Ssimon
186296341Sdelphij        /* Check public key OID matches public key type */
187296341Sdelphij        if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
188296341Sdelphij            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
189296341Sdelphij            goto err;
190296341Sdelphij        }
191238405Sjkim
192296341Sdelphij        if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) {
193296341Sdelphij            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
194296341Sdelphij            ret = 0;
195296341Sdelphij            goto err;
196296341Sdelphij        }
197238405Sjkim
198296341Sdelphij    }
199238405Sjkim
200296341Sdelphij    inl = ASN1_item_i2d(asn, &buf_in, it);
201109998Smarkm
202296341Sdelphij    if (buf_in == NULL) {
203296341Sdelphij        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
204296341Sdelphij        goto err;
205296341Sdelphij    }
206109998Smarkm
207296341Sdelphij    if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) {
208296341Sdelphij        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
209296341Sdelphij        ret = 0;
210296341Sdelphij        goto err;
211296341Sdelphij    }
212109998Smarkm
213296341Sdelphij    OPENSSL_cleanse(buf_in, (unsigned int)inl);
214296341Sdelphij    OPENSSL_free(buf_in);
215109998Smarkm
216296341Sdelphij    if (EVP_DigestVerifyFinal(&ctx, signature->data,
217296341Sdelphij                              (size_t)signature->length) <= 0) {
218296341Sdelphij        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
219296341Sdelphij        ret = 0;
220296341Sdelphij        goto err;
221296341Sdelphij    }
222296341Sdelphij    /*
223296341Sdelphij     * we don't need to zero the 'ctx' because we just checked public
224296341Sdelphij     * information
225296341Sdelphij     */
226296341Sdelphij    /* memset(&ctx,0,sizeof(ctx)); */
227296341Sdelphij    ret = 1;
228296341Sdelphij err:
229296341Sdelphij    EVP_MD_CTX_cleanup(&ctx);
230296341Sdelphij    return (ret);
231296341Sdelphij}
232