cmmfrec.c (10424B)
1 /* -*- Mode: C; tab-width: 8 -*-*/ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /* 7 * This file will implement the functions related to key recovery in 8 * CMMF 9 */ 10 11 #include "cmmf.h" 12 #include "cmmfi.h" 13 #include "secitem.h" 14 #include "keyhi.h" 15 16 CMMFKeyRecRepContent * 17 CMMF_CreateKeyRecRepContent(void) 18 { 19 PLArenaPool *poolp; 20 CMMFKeyRecRepContent *keyRecContent; 21 22 poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE); 23 if (poolp == NULL) { 24 return NULL; 25 } 26 keyRecContent = PORT_ArenaZNew(poolp, CMMFKeyRecRepContent); 27 if (keyRecContent == NULL) { 28 PORT_FreeArena(poolp, PR_FALSE); 29 return NULL; 30 } 31 keyRecContent->poolp = poolp; 32 return keyRecContent; 33 } 34 35 SECStatus 36 CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep) 37 { 38 PORT_Assert(inKeyRecRep != NULL); 39 if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) { 40 int i; 41 42 if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert != NULL) { 43 CERT_DestroyCertificate(inKeyRecRep->newSigCert); 44 } 45 if (inKeyRecRep->caCerts != NULL) { 46 for (i = 0; inKeyRecRep->caCerts[i] != NULL; i++) { 47 CERT_DestroyCertificate(inKeyRecRep->caCerts[i]); 48 } 49 } 50 if (inKeyRecRep->keyPairHist != NULL) { 51 for (i = 0; inKeyRecRep->keyPairHist[i] != NULL; i++) { 52 if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice == 53 cmmfCertificate) { 54 CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]->certOrEncCert.cert.certificate); 55 } 56 } 57 } 58 PORT_FreeArena(inKeyRecRep->poolp, PR_TRUE); 59 } 60 return SECSuccess; 61 } 62 63 SECStatus 64 CMMF_KeyRecRepContentSetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep, 65 CMMFPKIStatus inPKIStatus) 66 { 67 PORT_Assert(inKeyRecRep != NULL && inPKIStatus >= cmmfGranted && 68 inPKIStatus < cmmfNumPKIStatus); 69 if (inKeyRecRep == NULL) { 70 return SECFailure; 71 } 72 73 return cmmf_PKIStatusInfoSetStatus(&inKeyRecRep->status, 74 inKeyRecRep->poolp, 75 inPKIStatus); 76 } 77 78 SECStatus 79 CMMF_KeyRecRepContentSetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep, 80 CERTCertificate *inNewSignCert) 81 { 82 PORT_Assert(inKeyRecRep != NULL && inNewSignCert != NULL); 83 if (inKeyRecRep == NULL || inNewSignCert == NULL) { 84 return SECFailure; 85 } 86 if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert) { 87 CERT_DestroyCertificate(inKeyRecRep->newSigCert); 88 } 89 inKeyRecRep->isDecoded = PR_FALSE; 90 inKeyRecRep->newSigCert = CERT_DupCertificate(inNewSignCert); 91 return (inKeyRecRep->newSigCert == NULL) ? SECFailure : SECSuccess; 92 } 93 94 SECStatus 95 CMMF_KeyRecRepContentSetCACerts(CMMFKeyRecRepContent *inKeyRecRep, 96 CERTCertList *inCACerts) 97 { 98 SECStatus rv; 99 void *mark; 100 101 PORT_Assert(inKeyRecRep != NULL && inCACerts != NULL); 102 if (inKeyRecRep == NULL || inCACerts == NULL) { 103 return SECFailure; 104 } 105 mark = PORT_ArenaMark(inKeyRecRep->poolp); 106 rv = cmmf_ExtractCertsFromList(inCACerts, inKeyRecRep->poolp, 107 &inKeyRecRep->caCerts); 108 if (rv != SECSuccess) { 109 PORT_ArenaRelease(inKeyRecRep->poolp, mark); 110 } else { 111 PORT_ArenaUnmark(inKeyRecRep->poolp, mark); 112 } 113 return rv; 114 } 115 116 SECStatus 117 CMMF_KeyRecRepContentSetCertifiedKeyPair(CMMFKeyRecRepContent *inKeyRecRep, 118 CERTCertificate *inCert, 119 SECKEYPrivateKey *inPrivKey, 120 SECKEYPublicKey *inPubKey) 121 { 122 CMMFCertifiedKeyPair *keyPair; 123 CRMFEncryptedValue *dummy; 124 PLArenaPool *poolp; 125 void *mark; 126 SECStatus rv; 127 128 PORT_Assert(inKeyRecRep != NULL && 129 inCert != NULL && 130 inPrivKey != NULL && 131 inPubKey != NULL); 132 if (inKeyRecRep == NULL || 133 inCert == NULL || 134 inPrivKey == NULL || 135 inPubKey == NULL) { 136 return SECFailure; 137 } 138 poolp = inKeyRecRep->poolp; 139 mark = PORT_ArenaMark(poolp); 140 if (inKeyRecRep->keyPairHist == NULL) { 141 inKeyRecRep->keyPairHist = PORT_ArenaNewArray(poolp, 142 CMMFCertifiedKeyPair *, 143 (CMMF_MAX_KEY_PAIRS + 1)); 144 if (inKeyRecRep->keyPairHist == NULL) { 145 goto loser; 146 } 147 inKeyRecRep->allocKeyPairs = CMMF_MAX_KEY_PAIRS; 148 inKeyRecRep->numKeyPairs = 0; 149 } 150 151 if (inKeyRecRep->allocKeyPairs == inKeyRecRep->numKeyPairs) { 152 goto loser; 153 } 154 155 keyPair = PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair); 156 if (keyPair == NULL) { 157 goto loser; 158 } 159 rv = cmmf_CertOrEncCertSetCertificate(&keyPair->certOrEncCert, 160 poolp, inCert); 161 if (rv != SECSuccess) { 162 goto loser; 163 } 164 keyPair->privateKey = PORT_ArenaZNew(poolp, CRMFEncryptedValue); 165 if (keyPair->privateKey == NULL) { 166 goto loser; 167 } 168 dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, inPubKey, 169 keyPair->privateKey); 170 PORT_Assert(dummy == keyPair->privateKey); 171 if (dummy != keyPair->privateKey) { 172 crmf_destroy_encrypted_value(dummy, PR_TRUE); 173 goto loser; 174 } 175 inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = keyPair; 176 inKeyRecRep->numKeyPairs++; 177 inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = NULL; 178 PORT_ArenaUnmark(poolp, mark); 179 return SECSuccess; 180 181 loser: 182 PORT_ArenaRelease(poolp, mark); 183 return SECFailure; 184 } 185 186 CMMFPKIStatus 187 CMMF_KeyRecRepContentGetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep) 188 { 189 PORT_Assert(inKeyRecRep != NULL); 190 if (inKeyRecRep == NULL) { 191 return cmmfNoPKIStatus; 192 } 193 return cmmf_PKIStatusInfoGetStatus(&inKeyRecRep->status); 194 } 195 196 CERTCertificate * 197 CMMF_KeyRecRepContentGetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep) 198 { 199 PORT_Assert(inKeyRecRep != NULL); 200 if (inKeyRecRep == NULL || 201 inKeyRecRep->newSigCert == NULL) { 202 return NULL; 203 } 204 /* newSigCert may not be a real certificate, it may be a hand decoded 205 * cert structure. This code makes sure we hand off a real, fully formed 206 * CERTCertificate to the caller. TODO: This should move into the decode 207 * portion so that we never wind up with a half formed CERTCertificate 208 * here. In this case the call would be to CERT_DupCertificate. 209 */ 210 return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 211 &inKeyRecRep->newSigCert->signatureWrap.data, 212 NULL, PR_FALSE, PR_TRUE); 213 } 214 215 CERTCertList * 216 CMMF_KeyRecRepContentGetCACerts(CMMFKeyRecRepContent *inKeyRecRep) 217 { 218 PORT_Assert(inKeyRecRep != NULL); 219 if (inKeyRecRep == NULL || inKeyRecRep->caCerts == NULL) { 220 return NULL; 221 } 222 return cmmf_MakeCertList(inKeyRecRep->caCerts); 223 } 224 225 int 226 CMMF_KeyRecRepContentGetNumKeyPairs(CMMFKeyRecRepContent *inKeyRecRep) 227 { 228 PORT_Assert(inKeyRecRep != NULL); 229 return (inKeyRecRep == NULL) ? 0 : inKeyRecRep->numKeyPairs; 230 } 231 232 PRBool 233 cmmf_KeyRecRepContentIsValidIndex(CMMFKeyRecRepContent *inKeyRecRep, 234 int inIndex) 235 { 236 int numKeyPairs = CMMF_KeyRecRepContentGetNumKeyPairs(inKeyRecRep); 237 238 return (PRBool)(inIndex >= 0 && inIndex < numKeyPairs); 239 } 240 241 CMMFCertifiedKeyPair * 242 CMMF_KeyRecRepContentGetCertKeyAtIndex(CMMFKeyRecRepContent *inKeyRecRep, 243 int inIndex) 244 { 245 CMMFCertifiedKeyPair *newKeyPair; 246 SECStatus rv; 247 248 PORT_Assert(inKeyRecRep != NULL && 249 cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)); 250 if (inKeyRecRep == NULL || 251 !cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)) { 252 return NULL; 253 } 254 newKeyPair = PORT_ZNew(CMMFCertifiedKeyPair); 255 if (newKeyPair == NULL) { 256 return NULL; 257 } 258 rv = cmmf_CopyCertifiedKeyPair(NULL, newKeyPair, 259 inKeyRecRep->keyPairHist[inIndex]); 260 if (rv != SECSuccess) { 261 CMMF_DestroyCertifiedKeyPair(newKeyPair); 262 newKeyPair = NULL; 263 } 264 return newKeyPair; 265 } 266 267 SECStatus 268 CMMF_CertifiedKeyPairUnwrapPrivKey(CMMFCertifiedKeyPair *inKeyPair, 269 SECKEYPrivateKey *inPrivKey, 270 SECItem *inNickName, 271 PK11SlotInfo *inSlot, 272 CERTCertDBHandle *inCertdb, 273 SECKEYPrivateKey **destPrivKey, 274 void *wincx) 275 { 276 CERTCertificate *cert; 277 SECItem keyUsageValue = { siBuffer, NULL, 0 }; 278 unsigned char keyUsage = 0x0; 279 SECKEYPublicKey *pubKey; 280 SECStatus rv; 281 282 PORT_Assert(inKeyPair != NULL && 283 inPrivKey != NULL && inCertdb != NULL); 284 if (inKeyPair == NULL || 285 inPrivKey == NULL || 286 inKeyPair->privateKey == NULL || 287 inCertdb == NULL) { 288 return SECFailure; 289 } 290 291 cert = CMMF_CertifiedKeyPairGetCertificate(inKeyPair, inCertdb); 292 CERT_FindKeyUsageExtension(cert, &keyUsageValue); 293 if (keyUsageValue.data != NULL) { 294 keyUsage = keyUsageValue.len ? keyUsageValue.data[0] : 0; 295 PORT_Free(keyUsageValue.data); 296 } 297 pubKey = CERT_ExtractPublicKey(cert); 298 rv = crmf_encrypted_value_unwrap_priv_key(NULL, inKeyPair->privateKey, 299 inPrivKey, pubKey, 300 inNickName, inSlot, keyUsage, 301 destPrivKey, wincx); 302 SECKEY_DestroyPublicKey(pubKey); 303 CERT_DestroyCertificate(cert); 304 return rv; 305 } 306 307 PRBool 308 CMMF_KeyRecRepContentHasCACerts(CMMFKeyRecRepContent *inKeyRecRep) 309 { 310 PORT_Assert(inKeyRecRep != NULL); 311 if (inKeyRecRep == NULL) { 312 return PR_FALSE; 313 } 314 return (PRBool)(inKeyRecRep->caCerts != NULL && 315 inKeyRecRep->caCerts[0] != NULL); 316 }