Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@chromium.org>2016-01-01 09:17:30 +0300
committerAdam Langley <agl@google.com>2016-02-17 20:24:10 +0300
commite30a09e6049d8e6451da936e66f1591648a06d2e (patch)
tree9763d2b5da2217e13d0d1cd938c28d3cd66d4cf1 /crypto
parent440f1037716eca16f203edb8f03d4a59c92ae0cc (diff)
Implement new PKCS#8 parsers.
As with SPKI parsers, the intent is make EVP_PKEY capture the key's constraints in full fidelity, so we'd have to add new types or store the information in the underlying key object if people introduce variant key types with weird constraints on them. Note that because PKCS#8 has a space for arbitrary attributes, this parser must admit a hole. I'm assuming for now that we don't need an API that enforces no attributes and just ignore trailing data in the structure for simplicity. BUG=499653 Change-Id: I6fc641355e87136c7220f5d7693566d1144a68e8 Reviewed-on: https://boringssl-review.googlesource.com/6866 Reviewed-by: Adam Langley <agl@google.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/evp/evp_asn1.c48
-rw-r--r--crypto/evp/evp_test.cc57
-rw-r--r--crypto/evp/evp_tests.txt65
-rw-r--r--crypto/evp/internal.h12
-rw-r--r--crypto/evp/p_dsa_asn1.c143
-rw-r--r--crypto/evp/p_ec.c1
-rw-r--r--crypto/evp/p_ec_asn1.c158
-rw-r--r--crypto/evp/p_rsa_asn1.c44
-rw-r--r--crypto/pkcs8/pkcs8.c86
-rw-r--r--crypto/test/file_test.cc2
10 files changed, 242 insertions, 374 deletions
diff --git a/crypto/evp/evp_asn1.c b/crypto/evp/evp_asn1.c
index e90bed5f..ed7ae8b7 100644
--- a/crypto/evp/evp_asn1.c
+++ b/crypto/evp/evp_asn1.c
@@ -114,6 +114,54 @@ int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
return key->ameth->pub_encode(cbb, key);
}
+EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
+ /* Parse the PrivateKeyInfo. */
+ CBS pkcs8, algorithm, oid, key;
+ uint64_t version;
+ if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&pkcs8, &version) ||
+ version != 0 ||
+ !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ return NULL;
+ }
+
+ /* A PrivateKeyInfo ends with a SET of Attributes which we ignore. */
+
+ /* Set up an |EVP_PKEY| of the appropriate type. */
+ EVP_PKEY *ret = EVP_PKEY_new();
+ if (ret == NULL ||
+ !EVP_PKEY_set_type(ret, OBJ_cbs2nid(&oid))) {
+ goto err;
+ }
+
+ /* Call into the type-specific PrivateKeyInfo decoding function. */
+ if (ret->ameth->priv_decode == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ goto err;
+ }
+ if (!ret->ameth->priv_decode(ret, &algorithm, &key)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ EVP_PKEY_free(ret);
+ return NULL;
+}
+
+int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
+ if (key->ameth->priv_encode == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+
+ return key->ameth->priv_encode(cbb, key);
+}
+
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
long len) {
EVP_PKEY *ret;
diff --git a/crypto/evp/evp_test.cc b/crypto/evp/evp_test.cc
index 4e7b56e3..a7dac2bf 100644
--- a/crypto/evp/evp_test.cc
+++ b/crypto/evp/evp_test.cc
@@ -70,13 +70,11 @@
#pragma warning(pop)
#endif
-#include <openssl/bio.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
-#include <openssl/pem.h>
#include "../test/file_test.h"
#include "../test/scoped_types.h"
@@ -121,29 +119,9 @@ static int GetKeyType(FileTest *t, const std::string &name) {
using KeyMap = std::map<std::string, ScopedEVP_PKEY>;
-// ImportPrivateKey evaluates a PrivateKey test in |t| and writes the resulting
-// private key to |key_map|.
-static bool ImportPrivateKey(FileTest *t, KeyMap *key_map) {
- const std::string &key_name = t->GetParameter();
- if (key_map->count(key_name) > 0) {
- t->PrintLine("Duplicate key '%s'.", key_name.c_str());
- return false;
- }
- const std::string &block = t->GetBlock();
- ScopedBIO bio(BIO_new_mem_buf(const_cast<char*>(block.data()), block.size()));
- if (!bio) {
- return false;
- }
- ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr, 0, nullptr));
- if (!pkey) {
- t->PrintLine("Error reading private key.");
- return false;
- }
- (*key_map)[key_name] = std::move(pkey);
- return true;
-}
-
-static bool ImportPublicKey(FileTest *t, KeyMap *key_map) {
+static bool ImportKey(FileTest *t, KeyMap *key_map,
+ EVP_PKEY *(*parse_func)(CBS *cbs),
+ int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) {
std::vector<uint8_t> input;
if (!t->GetBytes(&input, "Input")) {
return false;
@@ -151,7 +129,7 @@ static bool ImportPublicKey(FileTest *t, KeyMap *key_map) {
CBS cbs;
CBS_init(&cbs, input.data(), input.size());
- ScopedEVP_PKEY pkey(EVP_parse_public_key(&cbs));
+ ScopedEVP_PKEY pkey(parse_func(&cbs));
if (!pkey) {
return false;
}
@@ -165,18 +143,24 @@ static bool ImportPublicKey(FileTest *t, KeyMap *key_map) {
return false;
}
- // The encoding must round-trip.
+ // The key must re-encode correctly.
ScopedCBB cbb;
- uint8_t *spki;
- size_t spki_len;
+ uint8_t *der;
+ size_t der_len;
if (!CBB_init(cbb.get(), 0) ||
- !EVP_marshal_public_key(cbb.get(), pkey.get()) ||
- !CBB_finish(cbb.get(), &spki, &spki_len)) {
+ !marshal_func(cbb.get(), pkey.get()) ||
+ !CBB_finish(cbb.get(), &der, &der_len)) {
+ return false;
+ }
+ ScopedOpenSSLBytes free_der(der);
+
+ std::vector<uint8_t> output = input;
+ if (t->HasAttribute("Output") &&
+ !t->GetBytes(&output, "Output")) {
return false;
}
- ScopedOpenSSLBytes free_spki(spki);
- if (!t->ExpectBytesEqual(input.data(), input.size(), spki, spki_len)) {
- t->PrintLine("Re-encoding the SPKI did not match.");
+ if (!t->ExpectBytesEqual(output.data(), output.size(), der, der_len)) {
+ t->PrintLine("Re-encoding the key did not match.");
return false;
}
@@ -193,11 +177,12 @@ static bool ImportPublicKey(FileTest *t, KeyMap *key_map) {
static bool TestEVP(FileTest *t, void *arg) {
KeyMap *key_map = reinterpret_cast<KeyMap*>(arg);
if (t->GetType() == "PrivateKey") {
- return ImportPrivateKey(t, key_map);
+ return ImportKey(t, key_map, EVP_parse_private_key,
+ EVP_marshal_private_key);
}
if (t->GetType() == "PublicKey") {
- return ImportPublicKey(t, key_map);
+ return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key);
}
int (*key_op_init)(EVP_PKEY_CTX *ctx);
diff --git a/crypto/evp/evp_tests.txt b/crypto/evp/evp_tests.txt
index 2320125e..f0601b21 100644
--- a/crypto/evp/evp_tests.txt
+++ b/crypto/evp/evp_tests.txt
@@ -4,34 +4,8 @@
# RSA 2048 bit key.
PrivateKey = RSA-2048
------BEGIN PRIVATE KEY-----
-MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDNAIHqeyrh6gbV
-n3xz2f+5SglhXC5Lp8Y2zvCN01M+wxhVJbAVx2m5mnfWclv5w1Mqm25fZifV+4UW
-B2jT3anL01l0URcX3D0wnS/EfuQfl+Mq23+d2GShxHZ6Zm7NcbwarPXnUX9LOFlP
-6psF5C1a2pkSAIAT5FMWpNm7jtCGuI0odYusr5ItRqhotIXSOcm66w4rZFknEPQr
-LR6gpLSALAvsqzKPimiwBzvbVG/uqYCdKEmRKzkMFTK8finHZY+BdfrkbzQzL/h7
-yrPkBkm5hXeGnaDqcYNT8HInVIhpE2SHYNEivmduD8SD3SD/wxvalqMZZsmqLnWt
-A95H4cRPAgMBAAECggEAYCl6x5kbFnoG1rJHWLjL4gi+ubLZ7Jc4vYD5Ci41AF3X
-ziktnim6iFvTFv7x8gkTvArJDWsICLJBTYIQREHYYkozzgIzyPeApIs3Wv8C12cS
-IopwJITbP56+zM+77hcJ26GCgA2Unp5CFuC/81WDiPi9kNo3Oh2CdD7D+90UJ/0W
-glplejFpEuhpU2URfKL4RckJQF/KxV+JX8FdIDhsJu54yemQdQKaF4psHkzwwgDo
-qc+yfp0Vb4bmwq3CKxqEoc1cpbJ5CHXXlAfISzUjlcuBzD/tW7BDtp7eDAcgRVAC
-XO6MX0QBcLYSC7SOD3R7zY9SIRCFDfBDxCjf0YcFMQKBgQD2+WG0fLwDXTrt68fe
-hQqVa2Xs25z2B2QGPxWqSFU8WNly/mZ1BW413f3De/O58vYi7icTNyVoScm+8hdv
-6PfD+LuRujdN1TuvPeyBTSvewQwf3IjN0Wh28mse36PwlBl+301C/x+ylxEDuJjK
-hZxCcocIaoQqtBC7ac8tNa9r4wKBgQDUfnJKf/QQSLJwwlJKQQGHi3MVm7c9PbwY
-eyIOY1s1NPluJDoYTZP4YLa/u2txwe2aHh9FhYMCPDAelqaSwaCLU9DsnKkQEA2A
-RR47fcagG6xK7O+N95iEa8I1oIy7os9MBoBMwRIZ6VYIxxTj8UMNSR+tu6MqV1Gg
-T5d0WDTJpQKBgCHyRSu5uV39AoyRS/eZ8cp36JqV1Q08FtOE+EVfi9evnrPfo9WR
-2YQt7yNfdjCo5IwIj/ZkLhAXlFNakz4el2+oUJ/HKLLaDEoaCNf883q6rh/zABrK
-HcG7sF2d/7qhoJ9/se7zgjfZ68zHIrkzhDbd5xGREnmMJoCcGo3sQyBhAoGAH3UQ
-qmLC2N5KPFMoJ4H0HgLQ6LQCrnhDLkScSBEBYaEUA/AtAYgKjcyTgVLXlyGkcRpg
-esRHHr+WSBD5W+R6ReYEmeKfTJdzyDdzQE9gZjdyjC0DUbsDwybIu3OnIef6VEDq
-IXK7oUZfzDDcsNn4mTDoFaoff5cpqFfgDgM43VkCgYBNHw11b+d+AQmaZS9QqIt7
-aF3FvwCYHV0jdv0Mb+Kc1bY4c0R5MFpzrTwVmdOerjuuA1+9b+0Hwo3nBZM4eaBu
-SOamA2hu2OJWCl9q8fLCT69KqWDjghhvFe7c6aJJGucwaA3Uz3eLcPqoaCarMiNH
-fMkTd7GabVourqIZdgvu1Q==
------END PRIVATE KEY-----
+Type = RSA
+Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f02030100010282010060297ac7991b167a06d6b24758b8cbe208beb9b2d9ec9738bd80f90a2e35005dd7ce292d9e29ba885bd316fef1f20913bc0ac90d6b0808b2414d82104441d8624a33ce0233c8f780a48b375aff02d76712228a702484db3f9ebecccfbbee1709dba182800d949e9e4216e0bff3558388f8bd90da373a1d82743ec3fbdd1427fd16825a657a316912e8695365117ca2f845c909405fcac55f895fc15d20386c26ee78c9e99075029a178a6c1e4cf0c200e8a9cfb27e9d156f86e6c2adc22b1a84a1cd5ca5b2790875d79407c84b352395cb81cc3fed5bb043b69ede0c07204550025cee8c5f440170b6120bb48e0f747bcd8f522110850df043c428dfd187053102818100f6f961b47cbc035d3aedebc7de850a956b65ecdb9cf60764063f15aa48553c58d972fe6675056e35ddfdc37bf3b9f2f622ee271337256849c9bef2176fe8f7c3f8bb91ba374dd53baf3dec814d2bdec10c1fdc88cdd16876f26b1edfa3f094197edf4d42ff1fb2971103b898ca859c427287086a842ab410bb69cf2d35af6be302818100d47e724a7ff41048b270c2524a4101878b73159bb73d3dbc187b220e635b3534f96e243a184d93f860b6bfbb6b71c1ed9a1e1f458583023c301e96a692c1a08b53d0ec9ca910100d80451e3b7dc6a01bac4aecef8df798846bc235a08cbba2cf4c06804cc11219e95608c714e3f1430d491fadbba32a5751a04f97745834c9a502818021f2452bb9b95dfd028c914bf799f1ca77e89a95d50d3c16d384f8455f8bd7af9eb3dfa3d591d9842def235f7630a8e48c088ff6642e101794535a933e1e976fa8509fc728b2da0c4a1a08d7fcf37abaae1ff3001aca1dc1bbb05d9dffbaa1a09f7fb1eef38237d9ebccc722b9338436dde7119112798c26809c1a8dec4320610281801f7510aa62c2d8de4a3c53282781f41e02d0e8b402ae78432e449c48110161a11403f02d01880a8dcc938152d79721a4711a607ac4471ebf964810f95be47a45e60499e29f4c9773c83773404f606637728c2d0351bb03c326c8bb73a721e7fa5440ea2172bba1465fcc30dcb0d9f89930e815aa1f7f9729a857e00e0338dd590281804d1f0d756fe77e01099a652f50a88b7b685dc5bf00981d5d2376fd0c6fe29cd5b638734479305a73ad3c1599d39eae3bae035fbd6fed07c28de705933879a06e48e6a603686ed8e2560a5f6af1f2c24faf4aa960e382186f15eedce9a2491ae730680dd4cf778b70faa86826ab3223477cc91377b19a6d5a2eaea219760beed5
# The public half of the same key encoded as a SubjectPublicKeyInfo.
PublicKey = RSA-2048-SPKI
@@ -50,11 +24,25 @@ Error = DECODE_ERROR
# EC P-256 key
PrivateKey = P-256
------BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiocvtiiTxNH/xbnw
-+RdYBp+DUuCPoFpJ+NuSbLVyhyWhRANCAAQsFQ9CnOcPIWwlLPXgYs4fY5zV0WXH
-+JQkBywnGX14szuSDpXNtmTpkNzwz+oNlOKo5q+dDlgFbmUxBJJbn+bJ
------END PRIVATE KEY-----
+Type = EC
+Input = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same key as above with the optional public key omitted.
+PrivateKey = P-256-MissingPublic
+Type = EC
+Input = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725
+
+# The same key as above with redundant parameters.
+PrivateKey = P-256-ExtraParameters
+Type = EC
+Input = 308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00a06082a8648ce3d030107a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+# The key re-encodes with the parameters removed.
+Output = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same key, but with the redundant parameters in the ECPrivateKey mismatched.
+PrivateKey = P-256-BadInnerParameters
+Input = 308190020100301306072a8648ce3d020106082a8648ce3d0301070476307402010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00706052b81040022a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = GROUP_MISMATCH
# The public half of the same key encoded as a PublicKey.
PublicKey = P-256-SPKI
@@ -66,13 +54,18 @@ PublicKey = P-256-SPKI
Input = 3082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
Error = DECODE_ERROR
-# A DSA key.
-PublicKey = DSA-1024
+# A DSA private key.
+PrivateKey = DSA-1024
+Type = DSA
+Input = 308202650201003082023906072a8648ce3804013082022c02820101009e12fab3de12213501dd82aa10ca2d101d2d4ebfef4d2a3f8daa0fe0cedad8d6af85616aa2f3252c0a2b5a6db09e6f14900e0ddb8311876dd8f9669525f99ed65949e184d5064793271169a228680b95ec12f59a8e20b21f2b58eb2a2012d35bde2ee351822fe8f32d0a330565dcce5c672b7259c14b2433d0b5b2ca2b2db0ab626e8f13f47fe0345d904e7294bb038e9ce21a9e580b83356278706cfe768436c69de149ccff98b4aab8cb4f6385c9f102ce59346eaeef27e0ad222d53d6e89cc8cde5776dd00057b03f2d88ab3cedbafd7b585f0b7f7835e17a3728bbf25ea62572f245dc111f3ce39cb6ffacc31b0a2790e7bde90224ea9b09315362af3d2b022100f381dcf53ebf724f8b2e5ca82c010fb4b5eda9358d0fd88ed278589488b54fc3028201000c402a725dcc3a62e02bf4cf43cd17f4a493591220223669cf4193edab423ad08dfb552e308a6a57a5ffbc7cd0fb2087f81f8df0cb08ab2133287d2b6968714a94f633c940845a48a3e16708dde761cc6a8eab2d84db21b6ea5b07681493cc9c31fbc368b243f6ddf8c932a8b4038f44e7b15ca876344a147859f2b43b39458668ad5e0a1a9a669546dd2812e3b3617a0aef99d58e3bb4cc87fd94225e01d2dcc469a77268146c51918f18e8b4d70aa1f0c7623bcc52cf3731d38641b2d2830b7eecb2f09552ff137d046e494e7f33c3590002b16d1b97d936fda28f90c3ed3ca35338168ac16f77c3c57adc2e8f7c6c2256e41a5f65450590dbb5bcf06d66610423022100b0c768702743bc51242993a971a52889795444f7c6452203d0ce84fe6117d46e
+
+# A DSA public key.
+PublicKey = DSA-1024-SPKI
Type = DSA
Input = 308201b73082012c06072a8648ce3804013082011f02818100b3429b8b128c9079f9b72e86857e98d265e5d91661ed8b5f4cc56e5eed1e571da30186983a9dd76297eab73ee13a1db841f8800d04a7cab478af6cde2ea4a2868531af169a24858c6268efa39ceb7ed0d4227eb5bbb01124a2a5a26038c7bcfb8cc827f68f5202345166e4718596799b65c9def82828ce44e62e38e41a0d24b1021500c5a56c81ddd87f47e676546c56d05706421624cf0281810094de40d27314fe929e47ff9b1ac65cfc73ef38c4d381c890be6217b15039ae18190e6b421af8c0bda35a5cfd050f58ae2644adce83e68c8e5ba11729df56bbb21e227a60b816cc033fa799a38fe1ba5b4aa1801b6f841ce3df99feb3b4fb96950c960af13fa2ce920aabc12dd24ad2044a35063ea0e25f67f560f4cfbdc5598303818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a
# The same key as above, but without the parameters.
-PublicKey = DSA-1024-No-Params
+PublicKey = DSA-1024-SPKI-No-Params
Type = DSA
Input = 308192300906072a8648ce38040103818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
index ffe768ce..7fe707e1 100644
--- a/crypto/evp/internal.h
+++ b/crypto/evp/internal.h
@@ -106,8 +106,16 @@ struct evp_pkey_asn1_method_st {
int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
- int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf);
- int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk);
+ /* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the
+ * result into |out|. It returns one on success and zero on error. |params| is
+ * the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key|
+ * is the contents of the OCTET STRING privateKey field. */
+ int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key);
+
+ /* priv_encode encodes |key| as a PrivateKeyInfo and appends the result to
+ * |out|. It returns one on success and zero on error. */
+ int (*priv_encode)(CBB *out, const EVP_PKEY *key);
+
int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx);
diff --git a/crypto/evp/p_dsa_asn1.c b/crypto/evp/p_dsa_asn1.c
index bed23c3e..09f69090 100644
--- a/crypto/evp/p_dsa_asn1.c
+++ b/crypto/evp/p_dsa_asn1.c
@@ -55,11 +55,11 @@
#include <openssl/evp.h>
-#include <limits.h>
-
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/digest.h>
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -128,128 +128,69 @@ static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) {
return 1;
}
-static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
- const uint8_t *p, *pm;
- int pklen, pmlen;
- int ptype;
- void *pval;
- ASN1_STRING *pstr;
- X509_ALGOR *palg;
- ASN1_INTEGER *privkey = NULL;
- BN_CTX *ctx = NULL;
-
- /* In PKCS#8 DSA: you just get a private key integer and parameters in the
- * AlgorithmIdentifier the pubkey must be recalculated. */
-
- DSA *dsa = NULL;
+static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* See PKCS#11, v2.40, section 2.5. */
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
- return 0;
- }
- privkey = d2i_ASN1_INTEGER(NULL, &p, pklen);
- if (privkey == NULL || privkey->type == V_ASN1_NEG_INTEGER) {
- goto decerr;
+ /* Decode parameters. */
+ BN_CTX *ctx = NULL;
+ DSA *dsa = DSA_parse_parameters(params);
+ if (dsa == NULL || CBS_len(params) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ goto err;
}
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
- if (ptype != V_ASN1_SEQUENCE) {
- goto decerr;
- }
- pstr = pval;
- pm = pstr->data;
- pmlen = pstr->length;
- dsa = d2i_DSAparams(NULL, &pm, pmlen);
- if (dsa == NULL) {
- goto decerr;
- }
- /* We have parameters. Now set private key */
- dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL);
- if (dsa->priv_key == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
- goto dsaerr;
- }
- /* Calculate public key. */
+ dsa->priv_key = BN_new();
dsa->pub_key = BN_new();
- if (dsa->pub_key == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto dsaerr;
+ if (dsa->priv_key == NULL || dsa->pub_key == NULL) {
+ goto err;
}
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto dsaerr;
+
+ /* Decode the key. */
+ if (!BN_parse_asn1_unsigned(key, dsa->priv_key) ||
+ CBS_len(key) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ goto err;
}
- if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
- OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
- goto dsaerr;
+ /* Calculate the public key. */
+ ctx = BN_CTX_new();
+ if (ctx == NULL ||
+ !BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
+ goto err;
}
- EVP_PKEY_assign_DSA(pkey, dsa);
BN_CTX_free(ctx);
- ASN1_INTEGER_free(privkey);
-
+ EVP_PKEY_assign_DSA(out, dsa);
return 1;
-decerr:
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
-
-dsaerr:
+err:
BN_CTX_free(ctx);
- ASN1_INTEGER_free(privkey);
DSA_free(dsa);
return 0;
}
-static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
- ASN1_STRING *params = NULL;
- ASN1_INTEGER *prkey = NULL;
- uint8_t *dp = NULL;
- int dplen;
-
- if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key) {
+static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
+ const DSA *dsa = key->pkey.dsa;
+ if (dsa == NULL || dsa->priv_key == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
- goto err;
- }
-
- params = ASN1_STRING_new();
- if (!params) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
- if (params->length <= 0) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- params->type = V_ASN1_SEQUENCE;
-
- /* Get private key into integer. */
- prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
-
- if (!prkey) {
- OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
- goto err;
+ return 0;
}
- dplen = i2d_ASN1_INTEGER(prkey, &dp);
-
- ASN1_INTEGER_free(prkey);
- prkey = NULL;
-
- if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_dsa), 0,
- V_ASN1_SEQUENCE, params, dp, dplen)) {
- goto err;
+ /* See PKCS#11, v2.40, section 2.5. */
+ CBB pkcs8, algorithm, private_key;
+ if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+ !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&algorithm, NID_dsa) ||
+ !DSA_marshal_parameters(&algorithm, dsa) ||
+ !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+ !BN_marshal_asn1(&private_key, dsa->priv_key) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
+ return 0;
}
return 1;
-
-err:
- OPENSSL_free(dp);
- ASN1_STRING_free(params);
- ASN1_INTEGER_free(prkey);
- return 0;
}
static int int_dsa_size(const EVP_PKEY *pkey) {
diff --git a/crypto/evp/p_ec.c b/crypto/evp/p_ec.c
index f842c270..49521827 100644
--- a/crypto/evp/p_ec.c
+++ b/crypto/evp/p_ec.c
@@ -57,7 +57,6 @@
#include <string.h>
-#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/digest.h>
diff --git a/crypto/evp/p_ec_asn1.c b/crypto/evp/p_ec_asn1.c
index f072ffe0..14f38396 100644
--- a/crypto/evp/p_ec_asn1.c
+++ b/crypto/evp/p_ec_asn1.c
@@ -59,6 +59,8 @@
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
@@ -67,26 +69,6 @@
#include "internal.h"
-static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) {
- const EC_GROUP *group;
- int nid;
-
- if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
- return 0;
- }
-
- nid = EC_GROUP_get_curve_name(group);
- if (nid == NID_undef) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
- return 0;
- }
-
- *ppval = (void*) OBJ_nid2obj(nid);
- *pptype = V_ASN1_OBJECT;
- return 1;
-}
-
static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
const EC_KEY *ec_key = key->pkey.ec;
const EC_GROUP *group = EC_KEY_get0_group(ec_key);
@@ -164,124 +146,52 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
}
}
-static EC_KEY *eckey_type2param(int ptype, void *pval) {
- EC_KEY *eckey = NULL;
-
- if (ptype == V_ASN1_SEQUENCE) {
- ASN1_STRING *pstr = pval;
- const uint8_t *pm = pstr->data;
- int pmlen = pstr->length;
-
- eckey = d2i_ECParameters(NULL, &pm, pmlen);
- if (eckey == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- goto err;
- }
- } else if (ptype == V_ASN1_OBJECT) {
- ASN1_OBJECT *poid = pval;
-
- /* type == V_ASN1_OBJECT => the parameters are given
- * by an asn1 OID */
- eckey = EC_KEY_new_by_curve_name(OBJ_obj2nid(poid));
- if (eckey == NULL) {
- goto err;
- }
- } else {
+static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* See RFC 5915. */
+ EC_GROUP *group = EC_KEY_parse_parameters(params);
+ if (group == NULL || CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- goto err;
- }
-
- return eckey;
-
-err:
- if (eckey) {
- EC_KEY_free(eckey);
- }
- return NULL;
-}
-
-static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
- const uint8_t *p = NULL;
- void *pval;
- int ptype, pklen;
- EC_KEY *eckey = NULL;
- X509_ALGOR *palg;
-
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
+ EC_GROUP_free(group);
return 0;
}
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
- eckey = eckey_type2param(ptype, pval);
-
- if (!eckey) {
- goto ecliberr;
- }
-
- /* We have parameters now set private key */
- if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
+ EC_KEY *ec_key = EC_KEY_parse_private_key(key, group);
+ EC_GROUP_free(group);
+ if (ec_key == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- goto ecerr;
+ EC_KEY_free(ec_key);
+ return 0;
}
- EVP_PKEY_assign_EC_KEY(pkey, eckey);
+ EVP_PKEY_assign_EC_KEY(out, ec_key);
return 1;
-
-ecliberr:
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-ecerr:
- if (eckey) {
- EC_KEY_free(eckey);
- }
- return 0;
}
-static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
- EC_KEY *ec_key;
- uint8_t *ep, *p;
- int eplen, ptype;
- void *pval;
- unsigned int tmp_flags, old_flags;
-
- ec_key = pkey->pkey.ec;
-
- if (!eckey_param2type(&ptype, &pval, ec_key)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
+ const EC_KEY *ec_key = key->pkey.ec;
+ int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
+ if (curve_nid == NID_undef) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
return 0;
}
- /* set the private key */
-
- /* do not include the parameters in the SEC1 private key
- * see PKCS#11 12.11 */
- old_flags = EC_KEY_get_enc_flags(ec_key);
- tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
- EC_KEY_set_enc_flags(ec_key, tmp_flags);
- eplen = i2d_ECPrivateKey(ec_key, NULL);
- if (!eplen) {
- EC_KEY_set_enc_flags(ec_key, old_flags);
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- return 0;
- }
- ep = OPENSSL_malloc(eplen);
- if (!ep) {
- EC_KEY_set_enc_flags(ec_key, old_flags);
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- p = ep;
- if (!i2d_ECPrivateKey(ec_key, &p)) {
- EC_KEY_set_enc_flags(ec_key, old_flags);
- OPENSSL_free(ep);
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- return 0;
- }
- /* restore old encoding flags */
- EC_KEY_set_enc_flags(ec_key, old_flags);
+ /* Omit the redundant copy of the curve name. This contradicts RFC 5915 but
+ * aligns with PKCS #11. SEC 1 only says they may be omitted if known by other
+ * means. Both OpenSSL and NSS omit the redundant parameters, so we omit them
+ * as well. */
+ unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS;
- if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
- 0, ptype, pval, ep, eplen)) {
- OPENSSL_free(ep);
+ /* See RFC 5915. */
+ CBB pkcs8, algorithm, private_key;
+ if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+ !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&algorithm, NID_X9_62_id_ecPublicKey) ||
+ !OBJ_nid2cbb(&algorithm, curve_nid) ||
+ !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+ !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
diff --git a/crypto/evp/p_rsa_asn1.c b/crypto/evp/p_rsa_asn1.c
index dc6c0f99..6848cc47 100644
--- a/crypto/evp/p_rsa_asn1.c
+++ b/crypto/evp/p_rsa_asn1.c
@@ -121,39 +121,41 @@ static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) == 0;
}
-static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
- uint8_t *encoded;
- size_t encoded_len;
- if (!RSA_private_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) {
- return 0;
- }
-
- /* TODO(fork): const correctness in next line. */
- if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_rsaEncryption), 0,
- V_ASN1_NULL, NULL, encoded, encoded_len)) {
- OPENSSL_free(encoded);
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) {
+ CBB pkcs8, algorithm, null, private_key;
+ if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+ !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&algorithm, NID_rsaEncryption) ||
+ !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
+ !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+ !RSA_marshal_private_key(&private_key, key->pkey.rsa) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
-static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
- const uint8_t *p;
- int pklen;
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8)) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* Per RFC 3447, A.1, the parameters have type NULL. */
+ CBS null;
+ if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
+ CBS_len(&null) != 0 ||
+ CBS_len(params) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
- RSA *rsa = RSA_private_key_from_bytes(p, pklen);
- if (rsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_RSA_LIB);
+ RSA *rsa = RSA_parse_private_key(key);
+ if (rsa == NULL || CBS_len(key) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ RSA_free(rsa);
return 0;
}
- EVP_PKEY_assign_RSA(pkey, rsa);
+ EVP_PKEY_assign_RSA(out, rsa);
return 1;
}
diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c
index fdce544a..175a8855 100644
--- a/crypto/pkcs8/pkcs8.c
+++ b/crypto/pkcs8/pkcs8.c
@@ -62,6 +62,7 @@
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
+#include <openssl/bytestring.h>
#include <openssl/cipher.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -71,7 +72,6 @@
#include "internal.h"
#include "../bytestring/internal.h"
-#include "../evp/internal.h"
#define PKCS12_KEY_ID 1
@@ -591,72 +591,52 @@ err:
}
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
- EVP_PKEY *pkey = NULL;
- ASN1_OBJECT *algoid;
- char obj_tmp[80];
-
- if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) {
+ uint8_t *der = NULL;
+ int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der);
+ if (der_len < 0) {
return NULL;
}
- pkey = EVP_PKEY_new();
- if (pkey == NULL) {
- OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+ CBS cbs;
+ CBS_init(&cbs, der, (size_t)der_len);
+ EVP_PKEY *ret = EVP_parse_private_key(&cbs);
+ if (ret == NULL || CBS_len(&cbs) != 0) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+ EVP_PKEY_free(ret);
+ OPENSSL_free(der);
return NULL;
}
- if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
- i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
- ERR_add_error_data(2, "TYPE=", obj_tmp);
- goto error;
- }
-
- if (pkey->ameth->priv_decode) {
- if (!pkey->ameth->priv_decode(pkey, p8)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PRIVATE_KEY_DECODE_ERROR);
- goto error;
- }
- } else {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
- goto error;
- }
-
- return pkey;
-
-error:
- EVP_PKEY_free(pkey);
- return NULL;
+ OPENSSL_free(der);
+ return ret;
}
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
- PKCS8_PRIV_KEY_INFO *p8;
-
- p8 = PKCS8_PRIV_KEY_INFO_new();
- if (p8 == NULL) {
- OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
- return NULL;
+ CBB cbb;
+ uint8_t *der = NULL;
+ size_t der_len;
+ if (!CBB_init(&cbb, 0) ||
+ !EVP_marshal_private_key(&cbb, pkey) ||
+ !CBB_finish(&cbb, &der, &der_len) ||
+ der_len > LONG_MAX) {
+ CBB_cleanup(&cbb);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR);
+ goto err;
}
- p8->broken = PKCS8_OK;
- if (pkey->ameth) {
- if (pkey->ameth->priv_encode) {
- if (!pkey->ameth->priv_encode(p8, pkey)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PRIVATE_KEY_ENCODE_ERROR);
- goto error;
- }
- } else {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
- goto error;
- }
- } else {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
- goto error;
+ const uint8_t *p = der;
+ PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len);
+ if (p8 == NULL || p != der + der_len) {
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+ goto err;
}
+
+ OPENSSL_free(der);
return p8;
-error:
- PKCS8_PRIV_KEY_INFO_free(p8);
+err:
+ OPENSSL_free(der);
return NULL;
}
diff --git a/crypto/test/file_test.cc b/crypto/test/file_test.cc
index 4752f04a..6b725b9f 100644
--- a/crypto/test/file_test.cc
+++ b/crypto/test/file_test.cc
@@ -224,6 +224,7 @@ bool FileTest::GetBytes(std::vector<uint8_t> *out, const std::string &key) {
PrintLine("Error decoding value: %s", value.c_str());
return false;
}
+ out->clear();
out->reserve(value.size() / 2);
for (size_t i = 0; i < value.size(); i += 2) {
uint8_t hi, lo;
@@ -304,6 +305,7 @@ int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg,
t.GetAttributeOrDie("Error").c_str(),
ERR_reason_error_string(err));
failed = true;
+ ERR_clear_error();
continue;
}
ERR_clear_error();