2 * Copyright (C) 2012 Tobias Brunner
4 * Copyright (C) secunet Security Networks AG
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "pkcs8_builder.h"
19 #include <utils/debug.h>
21 #include <asn1/asn1.h>
22 #include <asn1/asn1_parser.h>
23 #include <crypto/pkcs5.h>
24 #include <credentials/keys/private_key.h>
27 * ASN.1 definition of a privateKeyInfo structure
29 static const asn1Object_t pkinfoObjects
[] = {
30 { 0, "privateKeyInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
31 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
32 { 1, "privateKeyAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 2 */
33 { 1, "privateKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 3 */
34 { 1, "attributes", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 4 */
35 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 5 */
36 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
38 #define PKINFO_PRIVATE_KEY_ALGORITHM 2
39 #define PKINFO_PRIVATE_KEY 3
42 * Load a generic private key from an ASN.1 encoded blob
44 static private_key_t
*parse_private_key(chunk_t blob
)
46 asn1_parser_t
*parser
;
47 chunk_t object
, params
= chunk_empty
;
49 private_key_t
*key
= NULL
;
50 key_type_t type
= KEY_ANY
;
51 builder_part_t part
= BUILD_BLOB_ASN1_DER
;
53 parser
= asn1_parser_create(pkinfoObjects
, blob
);
54 parser
->set_flags(parser
, FALSE
, TRUE
);
56 while (parser
->iterate(parser
, &objectID
, &object
))
60 case PKINFO_PRIVATE_KEY_ALGORITHM
:
62 int oid
= asn1_parse_algorithmIdentifier(object
,
63 parser
->get_level(parser
) + 1, ¶ms
);
68 /* TODO: parameters associated with such keys should be
69 * treated as restrictions later when signing (the type
70 * itself is already a restriction). However, the
71 * builders currently don't expect any parameters for
72 * RSA keys (we also only pass along the params, not the
73 * exact type, so we'd have to guess that params
74 * indicate RSA/PSS, but they are optional so that won't
75 * work for keys without specific restrictions) */
78 case OID_RSA_ENCRYPTION
:
81 case OID_EC_PUBLICKEY
:
86 part
= BUILD_EDDSA_PRIV_ASN1_DER
;
90 part
= BUILD_EDDSA_PRIV_ASN1_DER
;
93 /* key type not supported */
98 case PKINFO_PRIVATE_KEY
:
100 DBG2(DBG_ASN
, "-- > --");
102 !chunk_equals(params
, chunk_from_chars(0x05, 0x00)))
104 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
105 type
, BUILD_BLOB_ALGID_PARAMS
,
106 params
, part
, object
, BUILD_END
);
110 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
111 type
, part
, object
, BUILD_END
);
113 DBG2(DBG_ASN
, "-- < --");
120 parser
->destroy(parser
);
125 * Try to decrypt the given blob using the given password and pkcs5 object.
127 static private_key_t
*decrypt_private_key_pw(key_type_t type
, pkcs5_t
*pkcs5
,
128 chunk_t blob
, chunk_t password
)
130 private_key_t
*private_key
;
133 if (!pkcs5
->decrypt(pkcs5
, password
, blob
, &decrypted
))
137 /* do a quick check to validate whether the password was correct */
138 if (!is_asn1(decrypted
))
140 chunk_clear(&decrypted
);
143 private_key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
144 type
, BUILD_BLOB_ASN1_DER
,
145 decrypted
, BUILD_END
);
146 chunk_clear(&decrypted
);
151 * Try to decrypt the given blob with multiple passwords using the given
154 static private_key_t
*decrypt_private_key(key_type_t type
, pkcs5_t
*pkcs5
,
157 enumerator_t
*enumerator
;
158 shared_key_t
*shared
;
159 private_key_t
*private_key
;
161 private_key
= decrypt_private_key_pw(type
, pkcs5
, blob
, chunk_empty
);
167 enumerator
= lib
->credmgr
->create_shared_enumerator(lib
->credmgr
,
168 SHARED_PRIVATE_KEY_PASS
, NULL
, NULL
);
169 while (enumerator
->enumerate(enumerator
, &shared
, NULL
, NULL
))
171 private_key
= decrypt_private_key_pw(type
, pkcs5
, blob
,
172 shared
->get_key(shared
));
178 enumerator
->destroy(enumerator
);
183 * ASN.1 definition of an encryptedPrivateKeyInfo structure
185 static const asn1Object_t encryptedPKIObjects
[] = {
186 { 0, "encryptedPrivateKeyInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
187 { 1, "encryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 1 */
188 { 1, "encryptedData", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 2 */
189 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
191 #define EPKINFO_ENCRYPTION_ALGORITHM 1
192 #define EPKINFO_ENCRYPTED_DATA 2
195 * Load an encrypted private key from an ASN.1 encoded blob
196 * Schemes per PKCS#5 (RFC 2898)
198 static private_key_t
*parse_encrypted_private_key(key_type_t type
, chunk_t blob
)
200 asn1_parser_t
*parser
;
203 private_key_t
*key
= NULL
;
204 pkcs5_t
*pkcs5
= NULL
;
206 parser
= asn1_parser_create(encryptedPKIObjects
, blob
);
208 while (parser
->iterate(parser
, &objectID
, &object
))
212 case EPKINFO_ENCRYPTION_ALGORITHM
:
214 pkcs5
= pkcs5_from_algorithmIdentifier(object
,
215 parser
->get_level(parser
) + 1);
222 case EPKINFO_ENCRYPTED_DATA
:
224 key
= decrypt_private_key(type
, pkcs5
, object
);
232 parser
->destroy(parser
);
239 private_key_t
*pkcs8_private_key_load(key_type_t type
, va_list args
)
241 chunk_t blob
= chunk_empty
;
246 switch (va_arg(args
, builder_part_t
))
248 case BUILD_BLOB_ASN1_DER
:
249 blob
= va_arg(args
, chunk_t
);
258 /* we don't know whether it is encrypted or not, try both ways */
259 key
= parse_encrypted_private_key(type
, blob
);
262 key
= parse_private_key(blob
);