4 * Nss keys store that uses Simple Keys Store under the hood. Uses the
5 * Nss DB as a backing store for the finding keys, but the NSS DB is
6 * not written to by the keys store.
7 * So, if store->findkey is done and the key is not found in the simple
8 * keys store, the NSS DB is looked up.
9 * If store is called to adopt a key, that key is not written to the NSS
11 * Thus, the NSS DB can be used to pre-load keys and becomes an alternate
12 * source of keys for xmlsec
14 * This is free software; see Copyright file in the source
15 * distribution for precise wording.
17 * Copyright (c) 2003 America Online, Inc. All rights reserved.
29 #include <libxml/tree.h>
31 #include <xmlsec/xmlsec.h>
32 #include <xmlsec/buffer.h>
33 #include <xmlsec/base64.h>
34 #include <xmlsec/errors.h>
35 #include <xmlsec/xmltree.h>
37 #include <xmlsec/keysmngr.h>
39 #include <xmlsec/nss/crypto.h>
40 #include <xmlsec/nss/keysstore.h>
41 #include <xmlsec/nss/x509.h>
42 #include <xmlsec/nss/pkikeys.h>
44 /****************************************************************************
46 * Nss Keys Store. Uses Simple Keys Store under the hood
48 * Simple Keys Store ptr is located after xmlSecKeyStore
50 ***************************************************************************/
51 #define xmlSecNssKeysStoreSize \
52 (sizeof(xmlSecKeyStore) + sizeof(xmlSecKeyStorePtr))
54 #define xmlSecNssKeysStoreGetSS(store) \
55 ((xmlSecKeyStoreCheckSize((store), xmlSecNssKeysStoreSize)) ? \
56 (xmlSecKeyStorePtr*)(((xmlSecByte*)(store)) + sizeof(xmlSecKeyStore)) : \
57 (xmlSecKeyStorePtr*)NULL)
59 static int xmlSecNssKeysStoreInitialize (xmlSecKeyStorePtr store);
60 static void xmlSecNssKeysStoreFinalize (xmlSecKeyStorePtr store);
61 static xmlSecKeyPtr xmlSecNssKeysStoreFindKey (xmlSecKeyStorePtr store,
63 xmlSecKeyInfoCtxPtr keyInfoCtx);
65 static xmlSecKeyStoreKlass xmlSecNssKeysStoreKlass = {
66 sizeof(xmlSecKeyStoreKlass),
67 xmlSecNssKeysStoreSize,
70 BAD_CAST "NSS-keys-store", /* const xmlChar* name; */
72 /* constructors/destructor */
73 xmlSecNssKeysStoreInitialize, /* xmlSecKeyStoreInitializeMethod initialize; */
74 xmlSecNssKeysStoreFinalize, /* xmlSecKeyStoreFinalizeMethod finalize; */
75 xmlSecNssKeysStoreFindKey, /* xmlSecKeyStoreFindKeyMethod findKey; */
77 /* reserved for the future */
78 NULL, /* void* reserved0; */
79 NULL, /* void* reserved1; */
83 * xmlSecNssKeysStoreGetKlass:
85 * The Nss list based keys store klass.
87 * Returns: Nss list based keys store klass.
90 xmlSecNssKeysStoreGetKlass(void) {
91 return(&xmlSecNssKeysStoreKlass);
95 * xmlSecNssKeysStoreAdoptKey:
96 * @store: the pointer to Nss keys store.
97 * @key: the pointer to key.
99 * Adds @key to the @store.
101 * Returns: 0 on success or a negative value if an error occurs.
104 xmlSecNssKeysStoreAdoptKey(xmlSecKeyStorePtr store, xmlSecKeyPtr key) {
105 xmlSecKeyStorePtr *ss;
107 xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
108 xmlSecAssert2((key != NULL), -1);
110 ss = xmlSecNssKeysStoreGetSS(store);
111 xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
112 (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
114 return (xmlSecSimpleKeysStoreAdoptKey(*ss, key));
118 * xmlSecNssKeysStoreLoad:
119 * @store: the pointer to Nss keys store.
120 * @uri: the filename.
121 * @keysMngr: the pointer to associated keys manager.
123 * Reads keys from an XML file.
125 * Returns: 0 on success or a negative value if an error occurs.
128 xmlSecNssKeysStoreLoad(xmlSecKeyStorePtr store, const char *uri,
129 xmlSecKeysMngrPtr keysMngr) {
134 xmlSecKeyInfoCtx keyInfoCtx;
137 xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
138 xmlSecAssert2((uri != NULL), -1);
140 doc = xmlParseFile(uri);
142 xmlSecError(XMLSEC_ERRORS_HERE,
143 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
145 XMLSEC_ERRORS_R_XML_FAILED,
147 xmlSecErrorsSafeString(uri));
151 root = xmlDocGetRootElement(doc);
152 if(!xmlSecCheckNodeName(root, BAD_CAST "Keys", xmlSecNs)) {
153 xmlSecError(XMLSEC_ERRORS_HERE,
154 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
155 xmlSecErrorsSafeString(xmlSecNodeGetName(root)),
156 XMLSEC_ERRORS_R_INVALID_NODE,
157 "expected-node=<xmlsec:Keys>");
162 cur = xmlSecGetNextElementNode(root->children);
163 while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {
164 key = xmlSecKeyCreate();
166 xmlSecError(XMLSEC_ERRORS_HERE,
167 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
168 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
169 XMLSEC_ERRORS_R_INVALID_NODE,
171 xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
176 ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
178 xmlSecError(XMLSEC_ERRORS_HERE,
179 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
180 "xmlSecKeyInfoCtxInitialize",
181 XMLSEC_ERRORS_R_XMLSEC_FAILED,
182 XMLSEC_ERRORS_NO_MESSAGE);
183 xmlSecKeyDestroy(key);
188 keyInfoCtx.mode = xmlSecKeyInfoModeRead;
189 keyInfoCtx.keysMngr = keysMngr;
190 keyInfoCtx.flags = XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND |
191 XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
192 keyInfoCtx.keyReq.keyId = xmlSecKeyDataIdUnknown;
193 keyInfoCtx.keyReq.keyType = xmlSecKeyDataTypeAny;
194 keyInfoCtx.keyReq.keyUsage= xmlSecKeyDataUsageAny;
196 ret = xmlSecKeyInfoNodeRead(cur, key, &keyInfoCtx);
198 xmlSecError(XMLSEC_ERRORS_HERE,
199 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
200 "xmlSecKeyInfoNodeRead",
201 XMLSEC_ERRORS_R_XMLSEC_FAILED,
202 XMLSEC_ERRORS_NO_MESSAGE);
203 xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
204 xmlSecKeyDestroy(key);
208 xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
210 if(xmlSecKeyIsValid(key)) {
211 ret = xmlSecNssKeysStoreAdoptKey(store, key);
213 xmlSecError(XMLSEC_ERRORS_HERE,
214 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
215 "xmlSecNssKeysStoreAdoptKey",
216 XMLSEC_ERRORS_R_XMLSEC_FAILED,
217 XMLSEC_ERRORS_NO_MESSAGE);
218 xmlSecKeyDestroy(key);
223 /* we have an unknown key in our file, just ignore it */
224 xmlSecKeyDestroy(key);
226 cur = xmlSecGetNextElementNode(cur->next);
230 xmlSecError(XMLSEC_ERRORS_HERE,
231 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
232 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
233 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
234 XMLSEC_ERRORS_NO_MESSAGE);
244 * xmlSecNssKeysStoreSave:
245 * @store: the pointer to Nss keys store.
246 * @filename: the filename.
247 * @type: the saved keys type (public, private, ...).
249 * Writes keys from @store to an XML file.
251 * Returns: 0 on success or a negative value if an error occurs.
254 xmlSecNssKeysStoreSave(xmlSecKeyStorePtr store, const char *filename, xmlSecKeyDataType type) {
255 xmlSecKeyStorePtr *ss;
257 xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
258 xmlSecAssert2((filename != NULL), -1);
260 ss = xmlSecNssKeysStoreGetSS(store);
261 xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
262 (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
264 return (xmlSecSimpleKeysStoreSave(*ss, filename, type));
268 xmlSecNssKeysStoreInitialize(xmlSecKeyStorePtr store) {
269 xmlSecKeyStorePtr *ss;
271 xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
273 ss = xmlSecNssKeysStoreGetSS(store);
274 xmlSecAssert2((*ss == NULL), -1);
276 *ss = xmlSecKeyStoreCreate(xmlSecSimpleKeysStoreId);
278 xmlSecError(XMLSEC_ERRORS_HERE,
279 xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
280 "xmlSecKeyStoreCreate",
281 XMLSEC_ERRORS_R_XMLSEC_FAILED,
282 "xmlSecSimpleKeysStoreId");
290 xmlSecNssKeysStoreFinalize(xmlSecKeyStorePtr store) {
291 xmlSecKeyStorePtr *ss;
293 xmlSecAssert(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId));
295 ss = xmlSecNssKeysStoreGetSS(store);
296 xmlSecAssert((ss != NULL) && (*ss != NULL));
298 xmlSecKeyStoreDestroy(*ss);
302 xmlSecNssKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name,
303 xmlSecKeyInfoCtxPtr keyInfoCtx) {
304 xmlSecKeyStorePtr* ss;
305 xmlSecKeyPtr key = NULL;
306 xmlSecKeyPtr retval = NULL;
307 xmlSecKeyReqPtr keyReq = NULL;
308 CERTCertificate *cert = NULL;
309 SECKEYPublicKey *pubkey = NULL;
310 SECKEYPrivateKey *privkey = NULL;
311 xmlSecKeyDataPtr data = NULL;
312 xmlSecKeyDataPtr x509Data = NULL;
315 xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), NULL);
316 xmlSecAssert2(keyInfoCtx != NULL, NULL);
318 ss = xmlSecNssKeysStoreGetSS(store);
319 xmlSecAssert2(((ss != NULL) && (*ss != NULL)), NULL);
321 key = xmlSecKeyStoreFindKey(*ss, name, keyInfoCtx);
326 /* Try to find the key in the NSS DB, and construct an xmlSecKey.
327 * we must have a name to lookup keys in NSS DB.
333 /* what type of key are we looking for?
334 * TBD: For now, we'll look only for public/private keys using the
335 * name as a cert nickname. Later on, we can attempt to find
336 * symmetric keys using PK11_FindFixedKey
338 keyReq = &(keyInfoCtx->keyReq);
339 if (keyReq->keyType &
340 (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) {
341 cert = CERT_FindCertByNickname (CERT_GetDefaultCertDB(), (char *)name);
346 if (keyReq->keyType & xmlSecKeyDataTypePublic) {
347 pubkey = CERT_ExtractPublicKey(cert);
348 if (pubkey == NULL) {
349 xmlSecError(XMLSEC_ERRORS_HERE,
351 "CERT_ExtractPublicKey",
352 XMLSEC_ERRORS_R_CRYPTO_FAILED,
353 XMLSEC_ERRORS_NO_MESSAGE);
358 if (keyReq->keyType & xmlSecKeyDataTypePrivate) {
359 privkey = PK11_FindKeyByAnyCert(cert, NULL);
360 if (privkey == NULL) {
361 xmlSecError(XMLSEC_ERRORS_HERE,
363 "PK11_FindKeyByAnyCert",
364 XMLSEC_ERRORS_R_CRYPTO_FAILED,
365 XMLSEC_ERRORS_NO_MESSAGE);
370 data = xmlSecNssPKIAdoptKey(privkey, pubkey);
372 xmlSecError(XMLSEC_ERRORS_HERE,
374 "xmlSecNssPKIAdoptKey",
375 XMLSEC_ERRORS_R_XMLSEC_FAILED,
376 XMLSEC_ERRORS_NO_MESSAGE);
382 key = xmlSecKeyCreate();
384 xmlSecError(XMLSEC_ERRORS_HERE,
387 XMLSEC_ERRORS_R_XMLSEC_FAILED,
388 XMLSEC_ERRORS_NO_MESSAGE);
392 x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id);
393 if(x509Data == NULL) {
394 xmlSecError(XMLSEC_ERRORS_HERE,
396 "xmlSecKeyDataCreate",
397 XMLSEC_ERRORS_R_XMLSEC_FAILED,
399 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
403 ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, cert);
405 xmlSecError(XMLSEC_ERRORS_HERE,
407 "xmlSecNssKeyDataX509AdoptKeyCert",
408 XMLSEC_ERRORS_R_XMLSEC_FAILED,
410 xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
413 cert = CERT_DupCertificate(cert);
415 xmlSecError(XMLSEC_ERRORS_HERE,
417 "CERT_DupCertificate",
418 XMLSEC_ERRORS_R_CRYPTO_FAILED,
420 xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
424 ret = xmlSecNssKeyDataX509AdoptCert(x509Data, cert);
426 xmlSecError(XMLSEC_ERRORS_HERE,
428 "xmlSecNssKeyDataX509AdoptCert",
429 XMLSEC_ERRORS_R_XMLSEC_FAILED,
431 xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
436 ret = xmlSecKeySetValue(key, data);
438 xmlSecError(XMLSEC_ERRORS_HERE,
441 XMLSEC_ERRORS_R_XMLSEC_FAILED,
443 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
448 ret = xmlSecKeyAdoptData(key, x509Data);
450 xmlSecError(XMLSEC_ERRORS_HERE,
452 "xmlSecKeyAdoptData",
453 XMLSEC_ERRORS_R_XMLSEC_FAILED,
455 xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
466 CERT_DestroyCertificate(cert);
468 if (pubkey != NULL) {
469 SECKEY_DestroyPublicKey(pubkey);
471 if (privkey != NULL) {
472 SECKEY_DestroyPrivateKey(privkey);
475 xmlSecKeyDataDestroy(data);
477 if (x509Data != NULL) {
478 xmlSecKeyDataDestroy(x509Data);
481 xmlSecKeyDestroy(key);