security/nss/lib/crmf/cmmfrec.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial