summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/crmf/cmmfrec.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/crmf/cmmfrec.c')
-rw-r--r--security/nss/lib/crmf/cmmfrec.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/security/nss/lib/crmf/cmmfrec.c b/security/nss/lib/crmf/cmmfrec.c
new file mode 100644
index 000000000..5dfe1fcca
--- /dev/null
+++ b/security/nss/lib/crmf/cmmfrec.c
@@ -0,0 +1,316 @@
+/* -*- Mode: C; tab-width: 8 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * This file will implement the functions related to key recovery in
+ * CMMF
+ */
+
+#include "cmmf.h"
+#include "cmmfi.h"
+#include "secitem.h"
+#include "keyhi.h"
+
+CMMFKeyRecRepContent *
+CMMF_CreateKeyRecRepContent(void)
+{
+ PLArenaPool *poolp;
+ CMMFKeyRecRepContent *keyRecContent;
+
+ poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
+ if (poolp == NULL) {
+ return NULL;
+ }
+ keyRecContent = PORT_ArenaZNew(poolp, CMMFKeyRecRepContent);
+ if (keyRecContent == NULL) {
+ PORT_FreeArena(poolp, PR_FALSE);
+ return NULL;
+ }
+ keyRecContent->poolp = poolp;
+ return keyRecContent;
+}
+
+SECStatus
+CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep)
+{
+ PORT_Assert(inKeyRecRep != NULL);
+ if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) {
+ int i;
+
+ if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert != NULL) {
+ CERT_DestroyCertificate(inKeyRecRep->newSigCert);
+ }
+ if (inKeyRecRep->caCerts != NULL) {
+ for (i = 0; inKeyRecRep->caCerts[i] != NULL; i++) {
+ CERT_DestroyCertificate(inKeyRecRep->caCerts[i]);
+ }
+ }
+ if (inKeyRecRep->keyPairHist != NULL) {
+ for (i = 0; inKeyRecRep->keyPairHist[i] != NULL; i++) {
+ if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice ==
+ cmmfCertificate) {
+ CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]->certOrEncCert.cert.certificate);
+ }
+ }
+ }
+ PORT_FreeArena(inKeyRecRep->poolp, PR_TRUE);
+ }
+ return SECSuccess;
+}
+
+SECStatus
+CMMF_KeyRecRepContentSetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep,
+ CMMFPKIStatus inPKIStatus)
+{
+ PORT_Assert(inKeyRecRep != NULL && inPKIStatus >= cmmfGranted &&
+ inPKIStatus < cmmfNumPKIStatus);
+ if (inKeyRecRep == NULL) {
+ return SECFailure;
+ }
+
+ return cmmf_PKIStatusInfoSetStatus(&inKeyRecRep->status,
+ inKeyRecRep->poolp,
+ inPKIStatus);
+}
+
+SECStatus
+CMMF_KeyRecRepContentSetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep,
+ CERTCertificate *inNewSignCert)
+{
+ PORT_Assert(inKeyRecRep != NULL && inNewSignCert != NULL);
+ if (inKeyRecRep == NULL || inNewSignCert == NULL) {
+ return SECFailure;
+ }
+ if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert) {
+ CERT_DestroyCertificate(inKeyRecRep->newSigCert);
+ }
+ inKeyRecRep->isDecoded = PR_FALSE;
+ inKeyRecRep->newSigCert = CERT_DupCertificate(inNewSignCert);
+ return (inKeyRecRep->newSigCert == NULL) ? SECFailure : SECSuccess;
+}
+
+SECStatus
+CMMF_KeyRecRepContentSetCACerts(CMMFKeyRecRepContent *inKeyRecRep,
+ CERTCertList *inCACerts)
+{
+ SECStatus rv;
+ void *mark;
+
+ PORT_Assert(inKeyRecRep != NULL && inCACerts != NULL);
+ if (inKeyRecRep == NULL || inCACerts == NULL) {
+ return SECFailure;
+ }
+ mark = PORT_ArenaMark(inKeyRecRep->poolp);
+ rv = cmmf_ExtractCertsFromList(inCACerts, inKeyRecRep->poolp,
+ &inKeyRecRep->caCerts);
+ if (rv != SECSuccess) {
+ PORT_ArenaRelease(inKeyRecRep->poolp, mark);
+ } else {
+ PORT_ArenaUnmark(inKeyRecRep->poolp, mark);
+ }
+ return rv;
+}
+
+SECStatus
+CMMF_KeyRecRepContentSetCertifiedKeyPair(CMMFKeyRecRepContent *inKeyRecRep,
+ CERTCertificate *inCert,
+ SECKEYPrivateKey *inPrivKey,
+ SECKEYPublicKey *inPubKey)
+{
+ CMMFCertifiedKeyPair *keyPair;
+ CRMFEncryptedValue *dummy;
+ PLArenaPool *poolp;
+ void *mark;
+ SECStatus rv;
+
+ PORT_Assert(inKeyRecRep != NULL &&
+ inCert != NULL &&
+ inPrivKey != NULL &&
+ inPubKey != NULL);
+ if (inKeyRecRep == NULL ||
+ inCert == NULL ||
+ inPrivKey == NULL ||
+ inPubKey == NULL) {
+ return SECFailure;
+ }
+ poolp = inKeyRecRep->poolp;
+ mark = PORT_ArenaMark(poolp);
+ if (inKeyRecRep->keyPairHist == NULL) {
+ inKeyRecRep->keyPairHist = PORT_ArenaNewArray(poolp,
+ CMMFCertifiedKeyPair *,
+ (CMMF_MAX_KEY_PAIRS + 1));
+ if (inKeyRecRep->keyPairHist == NULL) {
+ goto loser;
+ }
+ inKeyRecRep->allocKeyPairs = CMMF_MAX_KEY_PAIRS;
+ inKeyRecRep->numKeyPairs = 0;
+ }
+
+ if (inKeyRecRep->allocKeyPairs == inKeyRecRep->numKeyPairs) {
+ goto loser;
+ }
+
+ keyPair = PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair);
+ if (keyPair == NULL) {
+ goto loser;
+ }
+ rv = cmmf_CertOrEncCertSetCertificate(&keyPair->certOrEncCert,
+ poolp, inCert);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ keyPair->privateKey = PORT_ArenaZNew(poolp, CRMFEncryptedValue);
+ if (keyPair->privateKey == NULL) {
+ goto loser;
+ }
+ dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, inPubKey,
+ keyPair->privateKey);
+ PORT_Assert(dummy == keyPair->privateKey);
+ if (dummy != keyPair->privateKey) {
+ crmf_destroy_encrypted_value(dummy, PR_TRUE);
+ goto loser;
+ }
+ inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = keyPair;
+ inKeyRecRep->numKeyPairs++;
+ inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = NULL;
+ PORT_ArenaUnmark(poolp, mark);
+ return SECSuccess;
+
+loser:
+ PORT_ArenaRelease(poolp, mark);
+ return SECFailure;
+}
+
+CMMFPKIStatus
+CMMF_KeyRecRepContentGetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep)
+{
+ PORT_Assert(inKeyRecRep != NULL);
+ if (inKeyRecRep == NULL) {
+ return cmmfNoPKIStatus;
+ }
+ return cmmf_PKIStatusInfoGetStatus(&inKeyRecRep->status);
+}
+
+CERTCertificate *
+CMMF_KeyRecRepContentGetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep)
+{
+ PORT_Assert(inKeyRecRep != NULL);
+ if (inKeyRecRep == NULL ||
+ inKeyRecRep->newSigCert == NULL) {
+ return NULL;
+ }
+ /* newSigCert may not be a real certificate, it may be a hand decoded
+ * cert structure. This code makes sure we hand off a real, fully formed
+ * CERTCertificate to the caller. TODO: This should move into the decode
+ * portion so that we never wind up with a half formed CERTCertificate
+ * here. In this case the call would be to CERT_DupCertificate.
+ */
+ return CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ &inKeyRecRep->newSigCert->signatureWrap.data,
+ NULL, PR_FALSE, PR_TRUE);
+}
+
+CERTCertList *
+CMMF_KeyRecRepContentGetCACerts(CMMFKeyRecRepContent *inKeyRecRep)
+{
+ PORT_Assert(inKeyRecRep != NULL);
+ if (inKeyRecRep == NULL || inKeyRecRep->caCerts == NULL) {
+ return NULL;
+ }
+ return cmmf_MakeCertList(inKeyRecRep->caCerts);
+}
+
+int
+CMMF_KeyRecRepContentGetNumKeyPairs(CMMFKeyRecRepContent *inKeyRecRep)
+{
+ PORT_Assert(inKeyRecRep != NULL);
+ return (inKeyRecRep == NULL) ? 0 : inKeyRecRep->numKeyPairs;
+}
+
+PRBool
+cmmf_KeyRecRepContentIsValidIndex(CMMFKeyRecRepContent *inKeyRecRep,
+ int inIndex)
+{
+ int numKeyPairs = CMMF_KeyRecRepContentGetNumKeyPairs(inKeyRecRep);
+
+ return (PRBool)(inIndex >= 0 && inIndex < numKeyPairs);
+}
+
+CMMFCertifiedKeyPair *
+CMMF_KeyRecRepContentGetCertKeyAtIndex(CMMFKeyRecRepContent *inKeyRecRep,
+ int inIndex)
+{
+ CMMFCertifiedKeyPair *newKeyPair;
+ SECStatus rv;
+
+ PORT_Assert(inKeyRecRep != NULL &&
+ cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex));
+ if (inKeyRecRep == NULL ||
+ !cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)) {
+ return NULL;
+ }
+ newKeyPair = PORT_ZNew(CMMFCertifiedKeyPair);
+ if (newKeyPair == NULL) {
+ return NULL;
+ }
+ rv = cmmf_CopyCertifiedKeyPair(NULL, newKeyPair,
+ inKeyRecRep->keyPairHist[inIndex]);
+ if (rv != SECSuccess) {
+ CMMF_DestroyCertifiedKeyPair(newKeyPair);
+ newKeyPair = NULL;
+ }
+ return newKeyPair;
+}
+
+SECStatus
+CMMF_CertifiedKeyPairUnwrapPrivKey(CMMFCertifiedKeyPair *inKeyPair,
+ SECKEYPrivateKey *inPrivKey,
+ SECItem *inNickName,
+ PK11SlotInfo *inSlot,
+ CERTCertDBHandle *inCertdb,
+ SECKEYPrivateKey **destPrivKey,
+ void *wincx)
+{
+ CERTCertificate *cert;
+ SECItem keyUsageValue = { siBuffer, NULL, 0 };
+ unsigned char keyUsage = 0x0;
+ SECKEYPublicKey *pubKey;
+ SECStatus rv;
+
+ PORT_Assert(inKeyPair != NULL &&
+ inPrivKey != NULL && inCertdb != NULL);
+ if (inKeyPair == NULL ||
+ inPrivKey == NULL ||
+ inKeyPair->privateKey == NULL ||
+ inCertdb == NULL) {
+ return SECFailure;
+ }
+
+ cert = CMMF_CertifiedKeyPairGetCertificate(inKeyPair, inCertdb);
+ CERT_FindKeyUsageExtension(cert, &keyUsageValue);
+ if (keyUsageValue.data != NULL) {
+ keyUsage = keyUsageValue.data[3];
+ PORT_Free(keyUsageValue.data);
+ }
+ pubKey = CERT_ExtractPublicKey(cert);
+ rv = crmf_encrypted_value_unwrap_priv_key(NULL, inKeyPair->privateKey,
+ inPrivKey, pubKey,
+ inNickName, inSlot, keyUsage,
+ destPrivKey, wincx);
+ SECKEY_DestroyPublicKey(pubKey);
+ CERT_DestroyCertificate(cert);
+ return rv;
+}
+
+PRBool
+CMMF_KeyRecRepContentHasCACerts(CMMFKeyRecRepContent *inKeyRecRep)
+{
+ PORT_Assert(inKeyRecRep != NULL);
+ if (inKeyRecRep == NULL) {
+ return PR_FALSE;
+ }
+ return (PRBool)(inKeyRecRep->caCerts != NULL &&
+ inKeyRecRep->caCerts[0] != NULL);
+}