xref: /freebsd/crypto/openssl/crypto/asn1/d2i_pr.c (revision aeb5019c481d34f2422c200e4751e24ec940fe3f)
174664626SKris Kennaway /* crypto/asn1/d2i_pr.c */
274664626SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
374664626SKris Kennaway  * All rights reserved.
474664626SKris Kennaway  *
574664626SKris Kennaway  * This package is an SSL implementation written
674664626SKris Kennaway  * by Eric Young (eay@cryptsoft.com).
774664626SKris Kennaway  * The implementation was written so as to conform with Netscapes SSL.
874664626SKris Kennaway  *
974664626SKris Kennaway  * This library is free for commercial and non-commercial use as long as
1074664626SKris Kennaway  * the following conditions are aheared to.  The following conditions
1174664626SKris Kennaway  * apply to all code found in this distribution, be it the RC4, RSA,
1274664626SKris Kennaway  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1374664626SKris Kennaway  * included with this distribution is covered by the same copyright terms
1474664626SKris Kennaway  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1574664626SKris Kennaway  *
1674664626SKris Kennaway  * Copyright remains Eric Young's, and as such any Copyright notices in
1774664626SKris Kennaway  * the code are not to be removed.
1874664626SKris Kennaway  * If this package is used in a product, Eric Young should be given attribution
1974664626SKris Kennaway  * as the author of the parts of the library used.
2074664626SKris Kennaway  * This can be in the form of a textual message at program startup or
2174664626SKris Kennaway  * in documentation (online or textual) provided with the package.
2274664626SKris Kennaway  *
2374664626SKris Kennaway  * Redistribution and use in source and binary forms, with or without
2474664626SKris Kennaway  * modification, are permitted provided that the following conditions
2574664626SKris Kennaway  * are met:
2674664626SKris Kennaway  * 1. Redistributions of source code must retain the copyright
2774664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
2874664626SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
2974664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer in the
3074664626SKris Kennaway  *    documentation and/or other materials provided with the distribution.
3174664626SKris Kennaway  * 3. All advertising materials mentioning features or use of this software
3274664626SKris Kennaway  *    must display the following acknowledgement:
3374664626SKris Kennaway  *    "This product includes cryptographic software written by
3474664626SKris Kennaway  *     Eric Young (eay@cryptsoft.com)"
3574664626SKris Kennaway  *    The word 'cryptographic' can be left out if the rouines from the library
3674664626SKris Kennaway  *    being used are not cryptographic related :-).
3774664626SKris Kennaway  * 4. If you include any Windows specific code (or a derivative thereof) from
3874664626SKris Kennaway  *    the apps directory (application code) you must include an acknowledgement:
3974664626SKris Kennaway  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4074664626SKris Kennaway  *
4174664626SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4274664626SKris Kennaway  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4374664626SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4474664626SKris Kennaway  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4574664626SKris Kennaway  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4674664626SKris Kennaway  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4774664626SKris Kennaway  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4874664626SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4974664626SKris Kennaway  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5074664626SKris Kennaway  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5174664626SKris Kennaway  * SUCH DAMAGE.
5274664626SKris Kennaway  *
5374664626SKris Kennaway  * The licence and distribution terms for any publically available version or
5474664626SKris Kennaway  * derivative of this code cannot be changed.  i.e. this code cannot simply be
5574664626SKris Kennaway  * copied and put under another distribution licence
5674664626SKris Kennaway  * [including the GNU Public Licence.]
5774664626SKris Kennaway  */
5874664626SKris Kennaway 
5974664626SKris Kennaway #include <stdio.h>
6074664626SKris Kennaway #include "cryptlib.h"
6174664626SKris Kennaway #include <openssl/bn.h>
6274664626SKris Kennaway #include <openssl/evp.h>
6374664626SKris Kennaway #include <openssl/objects.h>
641f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE
651f13597dSJung-uk Kim # include <openssl/engine.h>
661f13597dSJung-uk Kim #endif
671f13597dSJung-uk Kim #include <openssl/x509.h>
6874664626SKris Kennaway #include <openssl/asn1.h>
691f13597dSJung-uk Kim #include "asn1_locl.h"
7074664626SKris Kennaway 
713b4e3dcbSSimon L. B. Nielsen EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
7274664626SKris Kennaway                          long length)
7374664626SKris Kennaway {
7474664626SKris Kennaway     EVP_PKEY *ret;
7580815a77SJung-uk Kim     const unsigned char *p = *pp;
7674664626SKris Kennaway 
776f9291ceSJung-uk Kim     if ((a == NULL) || (*a == NULL)) {
786f9291ceSJung-uk Kim         if ((ret = EVP_PKEY_new()) == NULL) {
7974664626SKris Kennaway             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
8074664626SKris Kennaway             return (NULL);
8174664626SKris Kennaway         }
826f9291ceSJung-uk Kim     } else {
831f13597dSJung-uk Kim         ret = *a;
841f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE
856f9291ceSJung-uk Kim         if (ret->engine) {
861f13597dSJung-uk Kim             ENGINE_finish(ret->engine);
871f13597dSJung-uk Kim             ret->engine = NULL;
881f13597dSJung-uk Kim         }
891f13597dSJung-uk Kim #endif
901f13597dSJung-uk Kim     }
9174664626SKris Kennaway 
926f9291ceSJung-uk Kim     if (!EVP_PKEY_set_type(ret, type)) {
9374664626SKris Kennaway         ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
9474664626SKris Kennaway         goto err;
951f13597dSJung-uk Kim     }
961f13597dSJung-uk Kim 
971f13597dSJung-uk Kim     if (!ret->ameth->old_priv_decode ||
9880815a77SJung-uk Kim         !ret->ameth->old_priv_decode(ret, &p, length)) {
996f9291ceSJung-uk Kim         if (ret->ameth->priv_decode) {
100*aeb5019cSJung-uk Kim             EVP_PKEY *tmp;
1011f13597dSJung-uk Kim             PKCS8_PRIV_KEY_INFO *p8 = NULL;
10280815a77SJung-uk Kim             p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
1036f9291ceSJung-uk Kim             if (!p8)
1046f9291ceSJung-uk Kim                 goto err;
105*aeb5019cSJung-uk Kim             tmp = EVP_PKCS82PKEY(p8);
1061f13597dSJung-uk Kim             PKCS8_PRIV_KEY_INFO_free(p8);
107*aeb5019cSJung-uk Kim             if (tmp == NULL)
10880815a77SJung-uk Kim                 goto err;
109*aeb5019cSJung-uk Kim             EVP_PKEY_free(ret);
110*aeb5019cSJung-uk Kim             ret = tmp;
1116f9291ceSJung-uk Kim         } else {
1121f13597dSJung-uk Kim             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
1131f13597dSJung-uk Kim             goto err;
1141f13597dSJung-uk Kim         }
11574664626SKris Kennaway     }
11680815a77SJung-uk Kim     *pp = p;
1176f9291ceSJung-uk Kim     if (a != NULL)
1186f9291ceSJung-uk Kim         (*a) = ret;
11974664626SKris Kennaway     return (ret);
12074664626SKris Kennaway  err:
1216f9291ceSJung-uk Kim     if ((ret != NULL) && ((a == NULL) || (*a != ret)))
1226f9291ceSJung-uk Kim         EVP_PKEY_free(ret);
12374664626SKris Kennaway     return (NULL);
12474664626SKris Kennaway }
12574664626SKris Kennaway 
1266f9291ceSJung-uk Kim /*
1276f9291ceSJung-uk Kim  * This works like d2i_PrivateKey() except it automatically works out the
1286f9291ceSJung-uk Kim  * type
1296f9291ceSJung-uk Kim  */
130f579bf8eSKris Kennaway 
1313b4e3dcbSSimon L. B. Nielsen EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
132f579bf8eSKris Kennaway                              long length)
133f579bf8eSKris Kennaway {
134f579bf8eSKris Kennaway     STACK_OF(ASN1_TYPE) *inkey;
1353b4e3dcbSSimon L. B. Nielsen     const unsigned char *p;
136f579bf8eSKris Kennaway     int keytype;
137f579bf8eSKris Kennaway     p = *pp;
1386f9291ceSJung-uk Kim     /*
1396f9291ceSJung-uk Kim      * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
1406f9291ceSJung-uk Kim      * analyzing it we can determine the passed structure: this assumes the
1416f9291ceSJung-uk Kim      * input is surrounded by an ASN1 SEQUENCE.
142f579bf8eSKris Kennaway      */
1431f13597dSJung-uk Kim     inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
14480815a77SJung-uk Kim     p = *pp;
1456f9291ceSJung-uk Kim     /*
1466f9291ceSJung-uk Kim      * Since we only need to discern "traditional format" RSA and DSA keys we
1476f9291ceSJung-uk Kim      * can just count the elements.
148f579bf8eSKris Kennaway      */
1493b4e3dcbSSimon L. B. Nielsen     if (sk_ASN1_TYPE_num(inkey) == 6)
1503b4e3dcbSSimon L. B. Nielsen         keytype = EVP_PKEY_DSA;
1513b4e3dcbSSimon L. B. Nielsen     else if (sk_ASN1_TYPE_num(inkey) == 4)
1523b4e3dcbSSimon L. B. Nielsen         keytype = EVP_PKEY_EC;
1536f9291ceSJung-uk Kim     else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
1546f9291ceSJung-uk Kim                                               * traditional format */
15580815a77SJung-uk Kim         PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
1561f13597dSJung-uk Kim         EVP_PKEY *ret;
1571f13597dSJung-uk Kim 
1581f13597dSJung-uk Kim         sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
1596f9291ceSJung-uk Kim         if (!p8) {
1606f9291ceSJung-uk Kim             ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
1616f9291ceSJung-uk Kim                     ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
1621f13597dSJung-uk Kim             return NULL;
1631f13597dSJung-uk Kim         }
1641f13597dSJung-uk Kim         ret = EVP_PKCS82PKEY(p8);
1651f13597dSJung-uk Kim         PKCS8_PRIV_KEY_INFO_free(p8);
16680815a77SJung-uk Kim         if (ret == NULL)
16780815a77SJung-uk Kim             return NULL;
16880815a77SJung-uk Kim         *pp = p;
1691f13597dSJung-uk Kim         if (a) {
1701f13597dSJung-uk Kim             *a = ret;
1711f13597dSJung-uk Kim         }
1721f13597dSJung-uk Kim         return ret;
1736f9291ceSJung-uk Kim     } else
1746f9291ceSJung-uk Kim         keytype = EVP_PKEY_RSA;
175f579bf8eSKris Kennaway     sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
176f579bf8eSKris Kennaway     return d2i_PrivateKey(keytype, a, pp, length);
177f579bf8eSKris Kennaway }
178