| /* 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/. */ |
| |
| #include "cmmf.h" |
| #include "cmmfi.h" |
| |
| SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
| SEC_ASN1_MKSUB(SEC_AnyTemplate) |
| SEC_ASN1_MKSUB(SEC_IntegerTemplate) |
| SEC_ASN1_MKSUB(SEC_SignedCertificateTemplate) |
| |
| static const SEC_ASN1Template CMMFCertResponseTemplate[] = { |
| { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFCertResponse) }, |
| { SEC_ASN1_INTEGER, offsetof(CMMFCertResponse, certReqId) }, |
| { SEC_ASN1_INLINE, offsetof(CMMFCertResponse, status), |
| CMMFPKIStatusInfoTemplate }, |
| { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER, |
| offsetof(CMMFCertResponse, certifiedKeyPair), |
| CMMFCertifiedKeyPairTemplate }, |
| { 0 } |
| }; |
| |
| static const SEC_ASN1Template CMMFCertOrEncCertTemplate[] = { |
| { SEC_ASN1_ANY, offsetof(CMMFCertOrEncCert, derValue), NULL, |
| sizeof(CMMFCertOrEncCert) }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFCertifiedKeyPairTemplate[] = { |
| { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFCertifiedKeyPair) }, |
| { SEC_ASN1_INLINE, offsetof(CMMFCertifiedKeyPair, certOrEncCert), |
| CMMFCertOrEncCertTemplate }, |
| { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_POINTER | 0, |
| offsetof(CMMFCertifiedKeyPair, privateKey), |
| CRMFEncryptedValueTemplate }, |
| { SEC_ASN1_NO_STREAM | SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | |
| SEC_ASN1_XTRN | 1, |
| offsetof(CMMFCertifiedKeyPair, derPublicationInfo), |
| SEC_ASN1_SUB(SEC_AnyTemplate) }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFPKIStatusInfoTemplate[] = { |
| { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFPKIStatusInfo) }, |
| { SEC_ASN1_INTEGER, offsetof(CMMFPKIStatusInfo, status) }, |
| { SEC_ASN1_OPTIONAL | SEC_ASN1_UTF8_STRING, |
| offsetof(CMMFPKIStatusInfo, statusString) }, |
| { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING, |
| offsetof(CMMFPKIStatusInfo, failInfo) }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFSequenceOfCertsTemplate[] = { |
| { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 0, |
| SEC_ASN1_SUB(SEC_SignedCertificateTemplate) } |
| }; |
| |
| const SEC_ASN1Template CMMFRandTemplate[] = { |
| { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFRand) }, |
| { SEC_ASN1_INTEGER, offsetof(CMMFRand, integer) }, |
| { SEC_ASN1_OCTET_STRING, offsetof(CMMFRand, senderHash) }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFPOPODecKeyRespContentTemplate[] = { |
| { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, |
| offsetof(CMMFPOPODecKeyRespContent, responses), |
| SEC_ASN1_SUB(SEC_IntegerTemplate), |
| sizeof(CMMFPOPODecKeyRespContent) }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFCertOrEncCertEncryptedCertTemplate[] = { |
| { SEC_ASN1_CONTEXT_SPECIFIC | 1, |
| 0, |
| CRMFEncryptedValueTemplate }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFCertOrEncCertCertificateTemplate[] = { |
| { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
| 0, |
| SEC_ASN1_SUB(SEC_SignedCertificateTemplate) }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFCertRepContentTemplate[] = { |
| { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFCertRepContent) }, |
| { SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | |
| SEC_ASN1_CONTEXT_SPECIFIC | 1, |
| offsetof(CMMFCertRepContent, caPubs), |
| CMMFSequenceOfCertsTemplate }, |
| { SEC_ASN1_SEQUENCE_OF, offsetof(CMMFCertRepContent, response), |
| CMMFCertResponseTemplate }, |
| { 0 } |
| }; |
| |
| static const SEC_ASN1Template CMMFChallengeTemplate[] = { |
| { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFChallenge) }, |
| { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, |
| offsetof(CMMFChallenge, owf), |
| SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
| { SEC_ASN1_OCTET_STRING, offsetof(CMMFChallenge, witness) }, |
| { SEC_ASN1_ANY, offsetof(CMMFChallenge, senderDER) }, |
| { SEC_ASN1_OCTET_STRING, offsetof(CMMFChallenge, key) }, |
| { SEC_ASN1_OCTET_STRING, offsetof(CMMFChallenge, challenge) }, |
| { 0 } |
| }; |
| |
| const SEC_ASN1Template CMMFPOPODecKeyChallContentTemplate[] = { |
| { SEC_ASN1_SEQUENCE_OF, offsetof(CMMFPOPODecKeyChallContent, challenges), |
| CMMFChallengeTemplate, sizeof(CMMFPOPODecKeyChallContent) }, |
| { 0 } |
| }; |
| |
| SECStatus |
| cmmf_decode_process_cert_response(PLArenaPool *poolp, |
| CERTCertDBHandle *db, |
| CMMFCertResponse *inCertResp) |
| { |
| SECStatus rv = SECSuccess; |
| |
| if (inCertResp->certifiedKeyPair != NULL) { |
| rv = cmmf_decode_process_certified_key_pair(poolp, |
| db, |
| inCertResp->certifiedKeyPair); |
| } |
| return rv; |
| } |
| |
| static CERTCertificate * |
| cmmf_DecodeDERCertificate(CERTCertDBHandle *db, SECItem *derCert) |
| { |
| CERTCertificate *newCert; |
| |
| newCert = CERT_NewTempCertificate(db, derCert, NULL, PR_FALSE, PR_TRUE); |
| return newCert; |
| } |
| |
| static CMMFCertOrEncCertChoice |
| cmmf_get_certorenccertchoice_from_der(SECItem *der) |
| { |
| CMMFCertOrEncCertChoice retChoice; |
| |
| switch (der->data[0] & 0x0f) { |
| case 0: |
| retChoice = cmmfCertificate; |
| break; |
| case 1: |
| retChoice = cmmfEncryptedCert; |
| break; |
| default: |
| retChoice = cmmfNoCertOrEncCert; |
| break; |
| } |
| return retChoice; |
| } |
| |
| static SECStatus |
| cmmf_decode_process_certorenccert(PLArenaPool *poolp, |
| CERTCertDBHandle *db, |
| CMMFCertOrEncCert *inCertOrEncCert) |
| { |
| SECStatus rv = SECSuccess; |
| |
| inCertOrEncCert->choice = |
| cmmf_get_certorenccertchoice_from_der(&inCertOrEncCert->derValue); |
| |
| switch (inCertOrEncCert->choice) { |
| case cmmfCertificate: { |
| /* The DER has implicit tagging, so we gotta switch it to |
| * un-tagged in order for the ASN1 parser to understand it. |
| * Saving the bits that were changed. |
| */ |
| inCertOrEncCert->derValue.data[0] = 0x30; |
| inCertOrEncCert->cert.certificate = |
| cmmf_DecodeDERCertificate(db, &inCertOrEncCert->derValue); |
| if (inCertOrEncCert->cert.certificate == NULL) { |
| rv = SECFailure; |
| } |
| |
| } break; |
| case cmmfEncryptedCert: |
| PORT_Assert(poolp); |
| if (!poolp) { |
| PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| rv = SECFailure; |
| break; |
| } |
| inCertOrEncCert->cert.encryptedCert = |
| PORT_ArenaZNew(poolp, CRMFEncryptedValue); |
| if (inCertOrEncCert->cert.encryptedCert == NULL) { |
| rv = SECFailure; |
| break; |
| } |
| rv = SEC_ASN1Decode(poolp, inCertOrEncCert->cert.encryptedCert, |
| CMMFCertOrEncCertEncryptedCertTemplate, |
| (const char *)inCertOrEncCert->derValue.data, |
| inCertOrEncCert->derValue.len); |
| break; |
| default: |
| rv = SECFailure; |
| } |
| return rv; |
| } |
| |
| SECStatus |
| cmmf_decode_process_certified_key_pair(PLArenaPool *poolp, |
| CERTCertDBHandle *db, |
| CMMFCertifiedKeyPair *inCertKeyPair) |
| { |
| return cmmf_decode_process_certorenccert(poolp, |
| db, |
| &inCertKeyPair->certOrEncCert); |
| } |