You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
Implement new SPKI parsers. Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each with different ways to set signature parameters. SPKIs themselves can get complex with id-RSASSA-PSS keys which come with various constraints in the key parameters. This suggests we want a common in-library representation of an SPKI. This adds two new functions EVP_parse_public_key and EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and implements X509_PUBKEY functions with them. EVP_PKEY seems to have been intended to be able to express the supported SPKI types with full-fidelity, so these APIs will continue this. This means future support for id-RSASSA-PSS would *not* repurpose EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and the data pointer would be some (exposed, so the caller may still check key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX implementation would enforce the key constraints. If RSA_PSS_KEY would later need its own API, that code would move there, but that seems unlikely. Ideally we'd have a 1:1 correspondence with key OID, although we may have to fudge things if mistakes happen in standardization. (Whether or not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate EVP_PKEY type.) DSA parsing hooks are still implemented, missing parameters and all for now. This isn't any worse than before. Decoupling from the giant crypto/obj OID table will be a later task. BUG=522228 Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c Reviewed-on: https://boringssl-review.googlesource.com/6861 Reviewed-by: Adam Langley <agl@google.com>
пре 8 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. #include <openssl/evp.h>
  57. #include <string.h>
  58. #include <openssl/bytestring.h>
  59. #include <openssl/dsa.h>
  60. #include <openssl/ec_key.h>
  61. #include <openssl/err.h>
  62. #include <openssl/rsa.h>
  63. #include "internal.h"
  64. #include "../internal.h"
  65. static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = {
  66. &rsa_asn1_meth,
  67. &ec_asn1_meth,
  68. &dsa_asn1_meth,
  69. &ed25519_asn1_meth,
  70. };
  71. static int parse_key_type(CBS *cbs, int *out_type) {
  72. CBS oid;
  73. if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) {
  74. return 0;
  75. }
  76. for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) {
  77. const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i];
  78. if (CBS_len(&oid) == method->oid_len &&
  79. OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) {
  80. *out_type = method->pkey_id;
  81. return 1;
  82. }
  83. }
  84. return 0;
  85. }
  86. EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
  87. // Parse the SubjectPublicKeyInfo.
  88. CBS spki, algorithm, key;
  89. int type;
  90. uint8_t padding;
  91. if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) ||
  92. !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
  93. !parse_key_type(&algorithm, &type) ||
  94. !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) ||
  95. CBS_len(&spki) != 0 ||
  96. // Every key type defined encodes the key as a byte string with the same
  97. // conversion to BIT STRING.
  98. !CBS_get_u8(&key, &padding) ||
  99. padding != 0) {
  100. OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
  101. return NULL;
  102. }
  103. // Set up an |EVP_PKEY| of the appropriate type.
  104. EVP_PKEY *ret = EVP_PKEY_new();
  105. if (ret == NULL ||
  106. !EVP_PKEY_set_type(ret, type)) {
  107. goto err;
  108. }
  109. // Call into the type-specific SPKI decoding function.
  110. if (ret->ameth->pub_decode == NULL) {
  111. OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
  112. goto err;
  113. }
  114. if (!ret->ameth->pub_decode(ret, &algorithm, &key)) {
  115. goto err;
  116. }
  117. return ret;
  118. err:
  119. EVP_PKEY_free(ret);
  120. return NULL;
  121. }
  122. int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
  123. if (key->ameth == NULL || key->ameth->pub_encode == NULL) {
  124. OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
  125. return 0;
  126. }
  127. return key->ameth->pub_encode(cbb, key);
  128. }
  129. EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
  130. // Parse the PrivateKeyInfo.
  131. CBS pkcs8, algorithm, key;
  132. uint64_t version;
  133. int type;
  134. if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
  135. !CBS_get_asn1_uint64(&pkcs8, &version) ||
  136. version != 0 ||
  137. !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
  138. !parse_key_type(&algorithm, &type) ||
  139. !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
  140. OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
  141. return NULL;
  142. }
  143. // A PrivateKeyInfo ends with a SET of Attributes which we ignore.
  144. // Set up an |EVP_PKEY| of the appropriate type.
  145. EVP_PKEY *ret = EVP_PKEY_new();
  146. if (ret == NULL ||
  147. !EVP_PKEY_set_type(ret, type)) {
  148. goto err;
  149. }
  150. // Call into the type-specific PrivateKeyInfo decoding function.
  151. if (ret->ameth->priv_decode == NULL) {
  152. OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
  153. goto err;
  154. }
  155. if (!ret->ameth->priv_decode(ret, &algorithm, &key)) {
  156. goto err;
  157. }
  158. return ret;
  159. err:
  160. EVP_PKEY_free(ret);
  161. return NULL;
  162. }
  163. int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
  164. if (key->ameth == NULL || key->ameth->priv_encode == NULL) {
  165. OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
  166. return 0;
  167. }
  168. return key->ameth->priv_encode(cbb, key);
  169. }
  170. static EVP_PKEY *old_priv_decode(CBS *cbs, int type) {
  171. EVP_PKEY *ret = EVP_PKEY_new();
  172. if (ret == NULL) {
  173. return NULL;
  174. }
  175. switch (type) {
  176. case EVP_PKEY_EC: {
  177. EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL);
  178. if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) {
  179. EC_KEY_free(ec_key);
  180. goto err;
  181. }
  182. return ret;
  183. }
  184. case EVP_PKEY_DSA: {
  185. DSA *dsa = DSA_parse_private_key(cbs);
  186. if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) {
  187. DSA_free(dsa);
  188. goto err;
  189. }
  190. return ret;
  191. }
  192. case EVP_PKEY_RSA: {
  193. RSA *rsa = RSA_parse_private_key(cbs);
  194. if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
  195. RSA_free(rsa);
  196. goto err;
  197. }
  198. return ret;
  199. }
  200. default:
  201. OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
  202. goto err;
  203. }
  204. err:
  205. EVP_PKEY_free(ret);
  206. return NULL;
  207. }
  208. EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
  209. long len) {
  210. if (len < 0) {
  211. OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
  212. return NULL;
  213. }
  214. // Parse with the legacy format.
  215. CBS cbs;
  216. CBS_init(&cbs, *inp, (size_t)len);
  217. EVP_PKEY *ret = old_priv_decode(&cbs, type);
  218. if (ret == NULL) {
  219. // Try again with PKCS#8.
  220. ERR_clear_error();
  221. CBS_init(&cbs, *inp, (size_t)len);
  222. ret = EVP_parse_private_key(&cbs);
  223. if (ret == NULL) {
  224. return NULL;
  225. }
  226. if (ret->type != type) {
  227. OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
  228. EVP_PKEY_free(ret);
  229. return NULL;
  230. }
  231. }
  232. if (out != NULL) {
  233. EVP_PKEY_free(*out);
  234. *out = ret;
  235. }
  236. *inp = CBS_data(&cbs);
  237. return ret;
  238. }
  239. // num_elements parses one SEQUENCE from |in| and returns the number of elements
  240. // in it. On parse error, it returns zero.
  241. static size_t num_elements(const uint8_t *in, size_t in_len) {
  242. CBS cbs, sequence;
  243. CBS_init(&cbs, in, (size_t)in_len);
  244. if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
  245. return 0;
  246. }
  247. size_t count = 0;
  248. while (CBS_len(&sequence) > 0) {
  249. if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) {
  250. return 0;
  251. }
  252. count++;
  253. }
  254. return count;
  255. }
  256. EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
  257. if (len < 0) {
  258. OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
  259. return NULL;
  260. }
  261. // Parse the input as a PKCS#8 PrivateKeyInfo.
  262. CBS cbs;
  263. CBS_init(&cbs, *inp, (size_t)len);
  264. EVP_PKEY *ret = EVP_parse_private_key(&cbs);
  265. if (ret != NULL) {
  266. if (out != NULL) {
  267. EVP_PKEY_free(*out);
  268. *out = ret;
  269. }
  270. *inp = CBS_data(&cbs);
  271. return ret;
  272. }
  273. ERR_clear_error();
  274. // Count the elements to determine the legacy key format.
  275. switch (num_elements(*inp, (size_t)len)) {
  276. case 4:
  277. return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);
  278. case 6:
  279. return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len);
  280. default:
  281. return d2i_PrivateKey(EVP_PKEY_RSA, out, inp, len);
  282. }
  283. }
  284. int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
  285. switch (key->type) {
  286. case EVP_PKEY_RSA:
  287. return i2d_RSAPublicKey(key->pkey.rsa, outp);
  288. case EVP_PKEY_DSA:
  289. return i2d_DSAPublicKey(key->pkey.dsa, outp);
  290. case EVP_PKEY_EC:
  291. return i2o_ECPublicKey(key->pkey.ec, outp);
  292. default:
  293. OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
  294. return -1;
  295. }
  296. }