1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to.  The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 *    notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 *    notice, this list of conditions and the following disclaimer in the
29 *    documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 *    must display the following acknowledgement:
32 *    "This product includes cryptographic software written by
33 *     Eric Young (eay@cryptsoft.com)"
34 *    The word 'cryptographic' can be left out if the rouines from the library
35 *    being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 *    the apps directory (application code) you must include an acknowledgement:
38 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed.  i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57#include <openssl/evp.h>
58
59#include <string.h>
60
61#include <openssl/bytestring.h>
62#include <openssl/dsa.h>
63#include <openssl/ec_key.h>
64#include <openssl/err.h>
65#include <openssl/rsa.h>
66
67#include "internal.h"
68#include "../internal.h"
69
70
71static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = {
72    &rsa_asn1_meth,
73    &ec_asn1_meth,
74    &dsa_asn1_meth,
75    &ed25519_asn1_meth,
76};
77
78static int parse_key_type(CBS *cbs, int *out_type) {
79  CBS oid;
80  if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) {
81    return 0;
82  }
83
84  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) {
85    const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i];
86    if (CBS_len(&oid) == method->oid_len &&
87        OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) {
88      *out_type = method->pkey_id;
89      return 1;
90    }
91  }
92
93  return 0;
94}
95
96EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
97  /* Parse the SubjectPublicKeyInfo. */
98  CBS spki, algorithm, key;
99  int type;
100  uint8_t padding;
101  if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) ||
102      !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
103      !parse_key_type(&algorithm, &type) ||
104      !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) ||
105      CBS_len(&spki) != 0 ||
106      /* Every key type defined encodes the key as a byte string with the same
107       * conversion to BIT STRING. */
108      !CBS_get_u8(&key, &padding) ||
109      padding != 0) {
110    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
111    return NULL;
112  }
113
114  /* Set up an |EVP_PKEY| of the appropriate type. */
115  EVP_PKEY *ret = EVP_PKEY_new();
116  if (ret == NULL ||
117      !EVP_PKEY_set_type(ret, type)) {
118    goto err;
119  }
120
121  /* Call into the type-specific SPKI decoding function. */
122  if (ret->ameth->pub_decode == NULL) {
123    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
124    goto err;
125  }
126  if (!ret->ameth->pub_decode(ret, &algorithm, &key)) {
127    goto err;
128  }
129
130  return ret;
131
132err:
133  EVP_PKEY_free(ret);
134  return NULL;
135}
136
137int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
138  if (key->ameth == NULL || key->ameth->pub_encode == NULL) {
139    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
140    return 0;
141  }
142
143  return key->ameth->pub_encode(cbb, key);
144}
145
146EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
147  /* Parse the PrivateKeyInfo. */
148  CBS pkcs8, algorithm, key;
149  uint64_t version;
150  int type;
151  if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
152      !CBS_get_asn1_uint64(&pkcs8, &version) ||
153      version != 0 ||
154      !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
155      !parse_key_type(&algorithm, &type) ||
156      !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
157    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
158    return NULL;
159  }
160
161  /* A PrivateKeyInfo ends with a SET of Attributes which we ignore. */
162
163  /* Set up an |EVP_PKEY| of the appropriate type. */
164  EVP_PKEY *ret = EVP_PKEY_new();
165  if (ret == NULL ||
166      !EVP_PKEY_set_type(ret, type)) {
167    goto err;
168  }
169
170  /* Call into the type-specific PrivateKeyInfo decoding function. */
171  if (ret->ameth->priv_decode == NULL) {
172    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
173    goto err;
174  }
175  if (!ret->ameth->priv_decode(ret, &algorithm, &key)) {
176    goto err;
177  }
178
179  return ret;
180
181err:
182  EVP_PKEY_free(ret);
183  return NULL;
184}
185
186int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
187  if (key->ameth == NULL || key->ameth->priv_encode == NULL) {
188    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
189    return 0;
190  }
191
192  return key->ameth->priv_encode(cbb, key);
193}
194
195static EVP_PKEY *old_priv_decode(CBS *cbs, int type) {
196  EVP_PKEY *ret = EVP_PKEY_new();
197  if (ret == NULL) {
198    return NULL;
199  }
200
201  switch (type) {
202    case EVP_PKEY_EC: {
203      EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL);
204      if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) {
205        EC_KEY_free(ec_key);
206        goto err;
207      }
208      return ret;
209    }
210    case EVP_PKEY_DSA: {
211      DSA *dsa = DSA_parse_private_key(cbs);
212      if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) {
213        DSA_free(dsa);
214        goto err;
215      }
216      return ret;
217    }
218    case EVP_PKEY_RSA: {
219      RSA *rsa = RSA_parse_private_key(cbs);
220      if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
221        RSA_free(rsa);
222        goto err;
223      }
224      return ret;
225    }
226    default:
227      OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
228      goto err;
229  }
230
231err:
232  EVP_PKEY_free(ret);
233  return NULL;
234}
235
236EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
237                         long len) {
238  if (len < 0) {
239    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
240    return NULL;
241  }
242
243  /* Parse with the legacy format. */
244  CBS cbs;
245  CBS_init(&cbs, *inp, (size_t)len);
246  EVP_PKEY *ret = old_priv_decode(&cbs, type);
247  if (ret == NULL) {
248    /* Try again with PKCS#8. */
249    ERR_clear_error();
250    CBS_init(&cbs, *inp, (size_t)len);
251    ret = EVP_parse_private_key(&cbs);
252    if (ret == NULL) {
253      return NULL;
254    }
255    if (ret->type != type) {
256      OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
257      EVP_PKEY_free(ret);
258      return NULL;
259    }
260  }
261
262  if (out != NULL) {
263    EVP_PKEY_free(*out);
264    *out = ret;
265  }
266  *inp = CBS_data(&cbs);
267  return ret;
268}
269
270/* num_elements parses one SEQUENCE from |in| and returns the number of elements
271 * in it. On parse error, it returns zero. */
272static size_t num_elements(const uint8_t *in, size_t in_len) {
273  CBS cbs, sequence;
274  CBS_init(&cbs, in, (size_t)in_len);
275
276  if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
277    return 0;
278  }
279
280  size_t count = 0;
281  while (CBS_len(&sequence) > 0) {
282    if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) {
283      return 0;
284    }
285
286    count++;
287  }
288
289  return count;
290}
291
292EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
293  if (len < 0) {
294    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
295    return NULL;
296  }
297
298  /* Parse the input as a PKCS#8 PrivateKeyInfo. */
299  CBS cbs;
300  CBS_init(&cbs, *inp, (size_t)len);
301  EVP_PKEY *ret = EVP_parse_private_key(&cbs);
302  if (ret != NULL) {
303    if (out != NULL) {
304      EVP_PKEY_free(*out);
305      *out = ret;
306    }
307    *inp = CBS_data(&cbs);
308    return ret;
309  }
310  ERR_clear_error();
311
312  /* Count the elements to determine the legacy key format. */
313  switch (num_elements(*inp, (size_t)len)) {
314    case 4:
315      return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);
316
317    case 6:
318      return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len);
319
320    default:
321      return d2i_PrivateKey(EVP_PKEY_RSA, out, inp, len);
322  }
323}
324
325int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
326  switch (key->type) {
327    case EVP_PKEY_RSA:
328      return i2d_RSAPublicKey(key->pkey.rsa, outp);
329    case EVP_PKEY_DSA:
330      return i2d_DSAPublicKey(key->pkey.dsa, outp);
331    case EVP_PKEY_EC:
332      return i2o_ECPublicKey(key->pkey.ec, outp);
333    default:
334      OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
335      return -1;
336  }
337}
338