1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/crmf/cmmfrec.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,318 @@ 1.4 +/* -*- Mode: C; tab-width: 8 -*-*/ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * This file will implement the functions related to key recovery in 1.11 + * CMMF 1.12 + */ 1.13 + 1.14 +#include "cmmf.h" 1.15 +#include "cmmfi.h" 1.16 +#include "secitem.h" 1.17 +#include "keyhi.h" 1.18 + 1.19 +CMMFKeyRecRepContent* 1.20 +CMMF_CreateKeyRecRepContent(void) 1.21 +{ 1.22 + PLArenaPool *poolp; 1.23 + CMMFKeyRecRepContent *keyRecContent; 1.24 + 1.25 + poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE); 1.26 + if (poolp == NULL) { 1.27 + return NULL; 1.28 + } 1.29 + keyRecContent = PORT_ArenaZNew(poolp, CMMFKeyRecRepContent); 1.30 + if (keyRecContent == NULL) { 1.31 + PORT_FreeArena(poolp, PR_FALSE); 1.32 + return NULL; 1.33 + } 1.34 + keyRecContent->poolp = poolp; 1.35 + return keyRecContent; 1.36 +} 1.37 + 1.38 +SECStatus 1.39 +CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep) 1.40 +{ 1.41 + PORT_Assert(inKeyRecRep != NULL); 1.42 + if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) { 1.43 + int i; 1.44 + 1.45 + if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert != NULL) { 1.46 + CERT_DestroyCertificate(inKeyRecRep->newSigCert); 1.47 + } 1.48 + if (inKeyRecRep->caCerts != NULL) { 1.49 + for (i=0; inKeyRecRep->caCerts[i] != NULL; i++) { 1.50 + CERT_DestroyCertificate(inKeyRecRep->caCerts[i]); 1.51 + } 1.52 + } 1.53 + if (inKeyRecRep->keyPairHist != NULL) { 1.54 + for (i=0; inKeyRecRep->keyPairHist[i] != NULL; i++) { 1.55 + if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice == 1.56 + cmmfCertificate) { 1.57 + CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]-> 1.58 + certOrEncCert.cert.certificate); 1.59 + } 1.60 + } 1.61 + } 1.62 + PORT_FreeArena(inKeyRecRep->poolp, PR_TRUE); 1.63 + } 1.64 + return SECSuccess; 1.65 +} 1.66 + 1.67 +SECStatus 1.68 +CMMF_KeyRecRepContentSetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep, 1.69 + CMMFPKIStatus inPKIStatus) 1.70 +{ 1.71 + PORT_Assert(inKeyRecRep != NULL && inPKIStatus >= cmmfGranted && 1.72 + inPKIStatus < cmmfNumPKIStatus); 1.73 + if (inKeyRecRep == NULL) { 1.74 + return SECFailure; 1.75 + } 1.76 + 1.77 + return cmmf_PKIStatusInfoSetStatus(&inKeyRecRep->status, 1.78 + inKeyRecRep->poolp, 1.79 + inPKIStatus); 1.80 +} 1.81 + 1.82 +SECStatus 1.83 +CMMF_KeyRecRepContentSetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep, 1.84 + CERTCertificate *inNewSignCert) 1.85 +{ 1.86 + PORT_Assert (inKeyRecRep != NULL && inNewSignCert != NULL); 1.87 + if (inKeyRecRep == NULL || inNewSignCert == NULL) { 1.88 + return SECFailure; 1.89 + } 1.90 + if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert) { 1.91 + CERT_DestroyCertificate(inKeyRecRep->newSigCert); 1.92 + } 1.93 + inKeyRecRep->isDecoded = PR_FALSE; 1.94 + inKeyRecRep->newSigCert = CERT_DupCertificate(inNewSignCert); 1.95 + return (inKeyRecRep->newSigCert == NULL) ? SECFailure : SECSuccess; 1.96 +} 1.97 + 1.98 +SECStatus 1.99 +CMMF_KeyRecRepContentSetCACerts(CMMFKeyRecRepContent *inKeyRecRep, 1.100 + CERTCertList *inCACerts) 1.101 +{ 1.102 + SECStatus rv; 1.103 + void *mark; 1.104 + 1.105 + PORT_Assert (inKeyRecRep != NULL && inCACerts != NULL); 1.106 + if (inKeyRecRep == NULL || inCACerts == NULL) { 1.107 + return SECFailure; 1.108 + } 1.109 + mark = PORT_ArenaMark(inKeyRecRep->poolp); 1.110 + rv = cmmf_ExtractCertsFromList(inCACerts, inKeyRecRep->poolp, 1.111 + &inKeyRecRep->caCerts); 1.112 + if (rv != SECSuccess) { 1.113 + PORT_ArenaRelease(inKeyRecRep->poolp, mark); 1.114 + } else { 1.115 + PORT_ArenaUnmark(inKeyRecRep->poolp, mark); 1.116 + } 1.117 + return rv; 1.118 +} 1.119 + 1.120 +SECStatus 1.121 +CMMF_KeyRecRepContentSetCertifiedKeyPair(CMMFKeyRecRepContent *inKeyRecRep, 1.122 + CERTCertificate *inCert, 1.123 + SECKEYPrivateKey *inPrivKey, 1.124 + SECKEYPublicKey *inPubKey) 1.125 +{ 1.126 + CMMFCertifiedKeyPair *keyPair; 1.127 + CRMFEncryptedValue *dummy; 1.128 + PLArenaPool *poolp; 1.129 + void *mark; 1.130 + SECStatus rv; 1.131 + 1.132 + PORT_Assert (inKeyRecRep != NULL && 1.133 + inCert != NULL && 1.134 + inPrivKey != NULL && 1.135 + inPubKey != NULL); 1.136 + if (inKeyRecRep == NULL || 1.137 + inCert == NULL || 1.138 + inPrivKey == NULL || 1.139 + inPubKey == NULL) { 1.140 + return SECFailure; 1.141 + } 1.142 + poolp = inKeyRecRep->poolp; 1.143 + mark = PORT_ArenaMark(poolp); 1.144 + if (inKeyRecRep->keyPairHist == NULL) { 1.145 + inKeyRecRep->keyPairHist = PORT_ArenaNewArray(poolp, 1.146 + CMMFCertifiedKeyPair*, 1.147 + (CMMF_MAX_KEY_PAIRS+1)); 1.148 + if (inKeyRecRep->keyPairHist == NULL) { 1.149 + goto loser; 1.150 + } 1.151 + inKeyRecRep->allocKeyPairs = CMMF_MAX_KEY_PAIRS; 1.152 + inKeyRecRep->numKeyPairs = 0; 1.153 + } 1.154 + 1.155 + if (inKeyRecRep->allocKeyPairs == inKeyRecRep->numKeyPairs) { 1.156 + goto loser; 1.157 + } 1.158 + 1.159 + keyPair = PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair); 1.160 + if (keyPair == NULL) { 1.161 + goto loser; 1.162 + } 1.163 + rv = cmmf_CertOrEncCertSetCertificate(&keyPair->certOrEncCert, 1.164 + poolp, inCert); 1.165 + if (rv != SECSuccess) { 1.166 + goto loser; 1.167 + } 1.168 + keyPair->privateKey = PORT_ArenaZNew(poolp, CRMFEncryptedValue); 1.169 + if (keyPair->privateKey == NULL) { 1.170 + goto loser; 1.171 + } 1.172 + dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, inPubKey, 1.173 + keyPair->privateKey); 1.174 + PORT_Assert(dummy == keyPair->privateKey); 1.175 + if (dummy != keyPair->privateKey) { 1.176 + crmf_destroy_encrypted_value(dummy, PR_TRUE); 1.177 + goto loser; 1.178 + } 1.179 + inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = keyPair; 1.180 + inKeyRecRep->numKeyPairs++; 1.181 + inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = NULL; 1.182 + PORT_ArenaUnmark(poolp, mark); 1.183 + return SECSuccess; 1.184 + 1.185 + loser: 1.186 + PORT_ArenaRelease(poolp, mark); 1.187 + return SECFailure; 1.188 +} 1.189 + 1.190 +CMMFPKIStatus 1.191 +CMMF_KeyRecRepContentGetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep) 1.192 +{ 1.193 + PORT_Assert(inKeyRecRep != NULL); 1.194 + if (inKeyRecRep == NULL) { 1.195 + return cmmfNoPKIStatus; 1.196 + } 1.197 + return cmmf_PKIStatusInfoGetStatus(&inKeyRecRep->status); 1.198 +} 1.199 + 1.200 +CERTCertificate* 1.201 +CMMF_KeyRecRepContentGetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep) 1.202 +{ 1.203 + PORT_Assert(inKeyRecRep != NULL); 1.204 + if (inKeyRecRep == NULL || 1.205 + inKeyRecRep->newSigCert == NULL) { 1.206 + return NULL; 1.207 + } 1.208 + /* newSigCert may not be a real certificate, it may be a hand decoded 1.209 + * cert structure. This code makes sure we hand off a real, fully formed 1.210 + * CERTCertificate to the caller. TODO: This should move into the decode 1.211 + * portion so that we never wind up with a half formed CERTCertificate 1.212 + * here. In this case the call would be to CERT_DupCertificate. 1.213 + */ 1.214 + return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 1.215 + &inKeyRecRep->newSigCert->signatureWrap.data, 1.216 + NULL, PR_FALSE, PR_TRUE); 1.217 +} 1.218 + 1.219 +CERTCertList* 1.220 +CMMF_KeyRecRepContentGetCACerts(CMMFKeyRecRepContent *inKeyRecRep) 1.221 +{ 1.222 + PORT_Assert(inKeyRecRep != NULL); 1.223 + if (inKeyRecRep == NULL || inKeyRecRep->caCerts == NULL) { 1.224 + return NULL; 1.225 + } 1.226 + return cmmf_MakeCertList(inKeyRecRep->caCerts); 1.227 +} 1.228 + 1.229 +int 1.230 +CMMF_KeyRecRepContentGetNumKeyPairs(CMMFKeyRecRepContent *inKeyRecRep) 1.231 +{ 1.232 + PORT_Assert(inKeyRecRep != NULL); 1.233 + return (inKeyRecRep == NULL) ? 0 : inKeyRecRep->numKeyPairs; 1.234 +} 1.235 + 1.236 +PRBool 1.237 +cmmf_KeyRecRepContentIsValidIndex(CMMFKeyRecRepContent *inKeyRecRep, 1.238 + int inIndex) 1.239 +{ 1.240 + int numKeyPairs = CMMF_KeyRecRepContentGetNumKeyPairs(inKeyRecRep); 1.241 + 1.242 + return (PRBool)(inIndex >= 0 && inIndex < numKeyPairs); 1.243 +} 1.244 + 1.245 +CMMFCertifiedKeyPair* 1.246 +CMMF_KeyRecRepContentGetCertKeyAtIndex(CMMFKeyRecRepContent *inKeyRecRep, 1.247 + int inIndex) 1.248 +{ 1.249 + CMMFCertifiedKeyPair *newKeyPair; 1.250 + SECStatus rv; 1.251 + 1.252 + PORT_Assert(inKeyRecRep != NULL && 1.253 + cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)); 1.254 + if (inKeyRecRep == NULL || 1.255 + !cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)) { 1.256 + return NULL; 1.257 + } 1.258 + newKeyPair = PORT_ZNew(CMMFCertifiedKeyPair); 1.259 + if (newKeyPair == NULL) { 1.260 + return NULL; 1.261 + } 1.262 + rv = cmmf_CopyCertifiedKeyPair(NULL, newKeyPair, 1.263 + inKeyRecRep->keyPairHist[inIndex]); 1.264 + if (rv != SECSuccess) { 1.265 + CMMF_DestroyCertifiedKeyPair(newKeyPair); 1.266 + newKeyPair = NULL; 1.267 + } 1.268 + return newKeyPair; 1.269 +} 1.270 + 1.271 +SECStatus 1.272 +CMMF_CertifiedKeyPairUnwrapPrivKey(CMMFCertifiedKeyPair *inKeyPair, 1.273 + SECKEYPrivateKey *inPrivKey, 1.274 + SECItem *inNickName, 1.275 + PK11SlotInfo *inSlot, 1.276 + CERTCertDBHandle *inCertdb, 1.277 + SECKEYPrivateKey **destPrivKey, 1.278 + void *wincx) 1.279 +{ 1.280 + CERTCertificate *cert; 1.281 + SECItem keyUsageValue = {siBuffer, NULL, 0}; 1.282 + unsigned char keyUsage = 0x0; 1.283 + SECKEYPublicKey *pubKey; 1.284 + SECStatus rv; 1.285 + 1.286 + PORT_Assert(inKeyPair != NULL && 1.287 + inPrivKey != NULL && inCertdb != NULL); 1.288 + if (inKeyPair == NULL || 1.289 + inPrivKey == NULL || 1.290 + inKeyPair->privateKey == NULL || 1.291 + inCertdb == NULL) { 1.292 + return SECFailure; 1.293 + } 1.294 + 1.295 + cert = CMMF_CertifiedKeyPairGetCertificate(inKeyPair, inCertdb); 1.296 + CERT_FindKeyUsageExtension(cert, &keyUsageValue); 1.297 + if (keyUsageValue.data != NULL) { 1.298 + keyUsage = keyUsageValue.data[3]; 1.299 + PORT_Free(keyUsageValue.data); 1.300 + } 1.301 + pubKey = CERT_ExtractPublicKey(cert); 1.302 + rv = crmf_encrypted_value_unwrap_priv_key(NULL, inKeyPair->privateKey, 1.303 + inPrivKey, pubKey, 1.304 + inNickName, inSlot, keyUsage, 1.305 + destPrivKey, wincx); 1.306 + SECKEY_DestroyPublicKey(pubKey); 1.307 + CERT_DestroyCertificate(cert); 1.308 + return rv; 1.309 +} 1.310 + 1.311 + 1.312 +PRBool 1.313 +CMMF_KeyRecRepContentHasCACerts(CMMFKeyRecRepContent *inKeyRecRep) 1.314 +{ 1.315 + PORT_Assert(inKeyRecRep != NULL); 1.316 + if (inKeyRecRep == NULL) { 1.317 + return PR_FALSE; 1.318 + } 1.319 + return (PRBool)(inKeyRecRep->caCerts != NULL && 1.320 + inKeyRecRep->caCerts[0] != NULL); 1.321 +}