2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "pkcs8_builder.h"
18 #include <utils/debug.h>
20 #include <asn1/asn1.h>
21 #include <asn1/asn1_parser.h>
22 #include <crypto/pkcs5.h>
23 #include <credentials/keys/private_key.h>
26 * ASN.1 definition of a privateKeyInfo structure
28 static const asn1Object_t pkinfoObjects
[] = {
29 { 0, "privateKeyInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
30 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
31 { 1, "privateKeyAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 2 */
32 { 1, "privateKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 3 */
33 { 1, "attributes", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 4 */
34 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 5 */
35 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
37 #define PKINFO_PRIVATE_KEY_ALGORITHM 2
38 #define PKINFO_PRIVATE_KEY 3
41 * Load a generic private key from an ASN.1 encoded blob
43 static private_key_t
*parse_private_key(chunk_t blob
)
45 asn1_parser_t
*parser
;
46 chunk_t object
, params
= chunk_empty
;
48 private_key_t
*key
= NULL
;
49 key_type_t type
= KEY_ANY
;
50 builder_part_t part
= BUILD_BLOB_ASN1_DER
;
52 parser
= asn1_parser_create(pkinfoObjects
, blob
);
53 parser
->set_flags(parser
, FALSE
, TRUE
);
55 while (parser
->iterate(parser
, &objectID
, &object
))
59 case PKINFO_PRIVATE_KEY_ALGORITHM
:
61 int oid
= asn1_parse_algorithmIdentifier(object
,
62 parser
->get_level(parser
) + 1, ¶ms
);
67 /* TODO: parameters associated with such keys should be
68 * treated as restrictions later when signing (the type
69 * itself is already a restriction). However, the
70 * builders currently don't expect any parameters for
71 * RSA keys (we also only pass along the params, not the
72 * exact type, so we'd have to guess that params
73 * indicate RSA/PSS, but they are optional so that won't
74 * work for keys without specific restrictions) */
76 case OID_RSA_ENCRYPTION
:
79 case OID_EC_PUBLICKEY
:
84 part
= BUILD_EDDSA_PRIV_ASN1_DER
;
88 part
= BUILD_EDDSA_PRIV_ASN1_DER
;
91 /* key type not supported */
96 case PKINFO_PRIVATE_KEY
:
98 DBG2(DBG_ASN
, "-- > --");
101 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
102 type
, BUILD_BLOB_ALGID_PARAMS
,
103 params
, part
, object
, BUILD_END
);
107 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
108 type
, part
, object
, BUILD_END
);
110 DBG2(DBG_ASN
, "-- < --");
117 parser
->destroy(parser
);
122 * Try to decrypt the given blob with multiple passwords using the given
125 static private_key_t
*decrypt_private_key(pkcs5_t
*pkcs5
, chunk_t blob
)
127 enumerator_t
*enumerator
;
128 shared_key_t
*shared
;
129 private_key_t
*private_key
= NULL
;
131 enumerator
= lib
->credmgr
->create_shared_enumerator(lib
->credmgr
,
132 SHARED_PRIVATE_KEY_PASS
, NULL
, NULL
);
133 while (enumerator
->enumerate(enumerator
, &shared
, NULL
, NULL
))
137 if (!pkcs5
->decrypt(pkcs5
, shared
->get_key(shared
), blob
, &decrypted
))
141 private_key
= parse_private_key(decrypted
);
144 chunk_clear(&decrypted
);
147 chunk_free(&decrypted
);
149 enumerator
->destroy(enumerator
);
155 * ASN.1 definition of an encryptedPrivateKeyInfo structure
157 static const asn1Object_t encryptedPKIObjects
[] = {
158 { 0, "encryptedPrivateKeyInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
159 { 1, "encryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 1 */
160 { 1, "encryptedData", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 2 */
161 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
163 #define EPKINFO_ENCRYPTION_ALGORITHM 1
164 #define EPKINFO_ENCRYPTED_DATA 2
167 * Load an encrypted private key from an ASN.1 encoded blob
168 * Schemes per PKCS#5 (RFC 2898)
170 static private_key_t
*parse_encrypted_private_key(chunk_t blob
)
172 asn1_parser_t
*parser
;
175 private_key_t
*key
= NULL
;
176 pkcs5_t
*pkcs5
= NULL
;
178 parser
= asn1_parser_create(encryptedPKIObjects
, blob
);
180 while (parser
->iterate(parser
, &objectID
, &object
))
184 case EPKINFO_ENCRYPTION_ALGORITHM
:
186 pkcs5
= pkcs5_from_algorithmIdentifier(object
,
187 parser
->get_level(parser
) + 1);
194 case EPKINFO_ENCRYPTED_DATA
:
196 key
= decrypt_private_key(pkcs5
, object
);
204 parser
->destroy(parser
);
211 private_key_t
*pkcs8_private_key_load(key_type_t type
, va_list args
)
213 chunk_t blob
= chunk_empty
;
218 switch (va_arg(args
, builder_part_t
))
220 case BUILD_BLOB_ASN1_DER
:
221 blob
= va_arg(args
, chunk_t
);
230 /* we don't know whether it is encrypted or not, try both ways */
231 key
= parse_encrypted_private_key(blob
);
234 key
= parse_private_key(blob
);