xref: /freebsd/crypto/openssl/crypto/asn1/d2i_pr.c (revision 2f513db72b034fd5ef7f080b11be5c711c15186a)
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/bn.h>
13 #include <openssl/evp.h>
14 #include <openssl/objects.h>
15 #include <openssl/engine.h>
16 #include <openssl/x509.h>
17 #include <openssl/asn1.h>
18 #include "internal/asn1_int.h"
19 #include "internal/evp_int.h"
20 
21 EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
22                          long length)
23 {
24     EVP_PKEY *ret;
25     const unsigned char *p = *pp;
26 
27     if ((a == NULL) || (*a == NULL)) {
28         if ((ret = EVP_PKEY_new()) == NULL) {
29             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
30             return NULL;
31         }
32     } else {
33         ret = *a;
34 #ifndef OPENSSL_NO_ENGINE
35         ENGINE_finish(ret->engine);
36         ret->engine = NULL;
37 #endif
38     }
39 
40     if (!EVP_PKEY_set_type(ret, type)) {
41         ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
42         goto err;
43     }
44 
45     if (!ret->ameth->old_priv_decode ||
46         !ret->ameth->old_priv_decode(ret, &p, length)) {
47         if (ret->ameth->priv_decode) {
48             EVP_PKEY *tmp;
49             PKCS8_PRIV_KEY_INFO *p8 = NULL;
50             p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
51             if (!p8)
52                 goto err;
53             tmp = EVP_PKCS82PKEY(p8);
54             PKCS8_PRIV_KEY_INFO_free(p8);
55             if (tmp == NULL)
56                 goto err;
57             EVP_PKEY_free(ret);
58             ret = tmp;
59         } else {
60             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
61             goto err;
62         }
63     }
64     *pp = p;
65     if (a != NULL)
66         (*a) = ret;
67     return ret;
68  err:
69     if (a == NULL || *a != ret)
70         EVP_PKEY_free(ret);
71     return NULL;
72 }
73 
74 /*
75  * This works like d2i_PrivateKey() except it automatically works out the
76  * type
77  */
78 
79 EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
80                              long length)
81 {
82     STACK_OF(ASN1_TYPE) *inkey;
83     const unsigned char *p;
84     int keytype;
85     p = *pp;
86     /*
87      * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
88      * analyzing it we can determine the passed structure: this assumes the
89      * input is surrounded by an ASN1 SEQUENCE.
90      */
91     inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
92     p = *pp;
93     /*
94      * Since we only need to discern "traditional format" RSA and DSA keys we
95      * can just count the elements.
96      */
97     if (sk_ASN1_TYPE_num(inkey) == 6)
98         keytype = EVP_PKEY_DSA;
99     else if (sk_ASN1_TYPE_num(inkey) == 4)
100         keytype = EVP_PKEY_EC;
101     else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
102                                               * traditional format */
103         PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
104         EVP_PKEY *ret;
105 
106         sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
107         if (!p8) {
108             ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
109                     ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
110             return NULL;
111         }
112         ret = EVP_PKCS82PKEY(p8);
113         PKCS8_PRIV_KEY_INFO_free(p8);
114         if (ret == NULL)
115             return NULL;
116         *pp = p;
117         if (a) {
118             *a = ret;
119         }
120         return ret;
121     } else
122         keytype = EVP_PKEY_RSA;
123     sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
124     return d2i_PrivateKey(keytype, a, pp, length);
125 }
126