+++ /dev/null
-/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-/*
- * DecodedCert.cpp - object representing a decoded cert, in NSS
- * format, with extensions parsed and decoded (still in NSS format).
- *
- * Created 9/1/2000 by Doug Mitchell.
- * Copyright (c) 2000 by Apple Computer.
- */
-
-#include "DecodedCert.h"
-#include "clNssUtils.h"
-#include "cldebugging.h"
-#include "AppleX509CLSession.h"
-#include "CSPAttacher.h"
-#include <Security/cssmapple.h>
-#include <Security/oidscert.h>
-
-DecodedCert::DecodedCert(
- AppleX509CLSession &session)
- : DecodedItem(session)
-{
- memset(&mCert, 0, sizeof(mCert));
-}
-
-/* one-shot constructor, decoding from DER-encoded data */
-DecodedCert::DecodedCert(
- AppleX509CLSession &session,
- const CssmData &encodedCert)
- : DecodedItem(session)
-{
- memset(&mCert, 0, sizeof(mCert));
- PRErrorCode prtn = mCoder.decode(encodedCert.data(), encodedCert.length(),
- kSecAsn1SignedCertTemplate, &mCert);
- if(prtn) {
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
- mDecodedExtensions.decodeFromNss(mCert.tbs.extensions);
- mState = IS_DecodedAll;
-}
-
-DecodedCert::~DecodedCert()
-{
-}
-
-/* decode TBSCert and its extensions */
-void DecodedCert::decodeTbs(
- const CssmData &encodedTbs)
-{
- assert(mState == IS_Empty);
-
- memset(&mCert, 0, sizeof(mCert));
- PRErrorCode prtn = mCoder.decode(encodedTbs.data(), encodedTbs.length(),
- kSecAsn1TBSCertificateTemplate, &mCert.tbs);
- if(prtn) {
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
- mDecodedExtensions.decodeFromNss(mCert.tbs.extensions);
- mState = IS_DecodedTBS;
-}
-
-void DecodedCert::encodeExtensions()
-{
- NSS_TBSCertificate &tbs = mCert.tbs;
- assert(mState == IS_Building);
- assert(tbs.extensions == NULL);
-
- if(mDecodedExtensions.numExtensions() == 0) {
- /* no extensions, no error */
- return;
- }
- mDecodedExtensions.encodeToNss(tbs.extensions);
-}
-
-/*
- * FIXME : how to determine max encoding size at run time!?
- */
-#define MAX_TEMPLATE_SIZE (8 * 1024)
-
-/* encode TBS component; only called from CertCreateTemplate */
-void DecodedCert::encodeTbs(
- CssmOwnedData &encodedTbs)
-{
- encodeExtensions();
- assert(mState == IS_Building);
-
- /* enforce required fields - could go deeper, maybe we should */
- NSS_TBSCertificate &tbs = mCert.tbs;
- if((tbs.signature.algorithm.Data == NULL) ||
- (tbs.issuer.rdns == NULL) ||
- (tbs.subject.rdns == NULL) ||
- (tbs.subjectPublicKeyInfo.subjectPublicKey.Data == NULL)) {
- clErrorLog("DecodedCert::encodeTbs: incomplete TBS");
- /* an odd, undocumented error return */
- CssmError::throwMe(CSSMERR_CL_NO_FIELD_VALUES);
- }
-
- PRErrorCode prtn;
- prtn = SecNssEncodeItemOdata(&tbs, kSecAsn1TBSCertificateTemplate,
- encodedTbs);
- if(prtn) {
- CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
- }
-}
-
-/*
- * Cook up CSSM_KEYUSE, gleaning as much as possible from
- * (optional) extensions. If no applicable extensions available,
- * we'll just return CSSM_KEYUSE_ANY.
- *
- * Note that the standard KeyUsage flags involving 'signing' translate
- * to verify since we're only dealing with public keys.
- */
-CSSM_KEYUSE DecodedCert::inferKeyUsage() const
-{
- CSSM_KEYUSE keyUse = 0;
- const DecodedExten *decodedExten;
- uint32 numFields;
-
- /* Basic KeyUsage */
- decodedExten = DecodedItem::findDecodedExt(CSSMOID_KeyUsage, false,
- 0, numFields);
- if(decodedExten) {
- CSSM_DATA *ku = (CSSM_DATA *)decodedExten->nssObj();
- assert(ku != NULL);
- CE_KeyUsage kuse = clBitStringToKeyUsage(*ku);
- if(kuse & CE_KU_DigitalSignature) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- if(kuse & CE_KU_NonRepudiation) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- if(kuse & CE_KU_KeyEncipherment) {
- keyUse |= CSSM_KEYUSE_WRAP;
- }
- if(kuse & CE_KU_KeyAgreement) {
- keyUse |= CSSM_KEYUSE_DERIVE;
- }
- if(kuse & CE_KU_KeyCertSign) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- if(kuse & CE_KU_CRLSign) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- if(kuse & CE_KU_DataEncipherment) {
- keyUse |= CSSM_KEYUSE_ENCRYPT;
- }
- }
-
- /* Extended key usage */
- decodedExten = DecodedItem::findDecodedExt(CSSMOID_ExtendedKeyUsage,
- false, 0, numFields);
- if(decodedExten) {
- NSS_ExtKeyUsage *euse = (NSS_ExtKeyUsage *)decodedExten->nssObj();
- assert(euse != NULL);
- unsigned numUses = clNssArraySize((const void **)euse->purposes);
- for(unsigned dex=0; dex<numUses; dex++) {
- const CSSM_OID *thisUse = euse->purposes[dex];
- if(clCompareCssmData(thisUse, &CSSMOID_ExtendedKeyUsageAny)) {
- /* we're done */
- keyUse = CSSM_KEYUSE_ANY;
- break;
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_ServerAuth)) {
- keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DERIVE);
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_ClientAuth)) {
- keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DERIVE);
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_ExtendedUseCodeSigning)) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_EmailProtection)) {
- keyUse |=
- (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_DERIVE);
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_TimeStamping)) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_OCSPSigning)) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_APPLE_EKU_SYSTEM_IDENTITY)) {
- /* system identity - fairly liberal: CMS as well as SSL */
- keyUse |=
- (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_ENCRYPT);
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_KERBv5_PKINIT_KP_CLIENT_AUTH)) {
- /*
- * Kerberos PKINIT client:
- * -- KDC verifies client signature in a CMS msg in AS-REQ
- * -- KDC encrypts for client in a CMS msg in AS-REP
- */
- keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP);
- }
- else if(clCompareCssmData(thisUse, &CSSMOID_KERBv5_PKINIT_KP_KDC)) {
- /*
- * Kerberos PKINIT server:
- * -- client verifies KDC signature in a CMS msg in AS-REP
- */
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- }
- }
-
- /* NetscapeCertType */
- decodedExten = DecodedItem::findDecodedExt(CSSMOID_NetscapeCertType,
- false, 0, numFields);
- if(decodedExten) {
- /* nssObj() is a CSSM_DATA ptr, whose Data points to the bits we want */
- CSSM_DATA *nctData = (CSSM_DATA *)decodedExten->nssObj();
- if((nctData != NULL) && (nctData->Length > 0)) {
- CE_NetscapeCertType nct = ((uint16)nctData->Data[0]) << 8;
- if(nctData->Length > 1) {
- nct |= nctData->Data[1];
- }
-
- /* All this usage bits imply signature verify capability */
- if(nct & (CE_NCT_SSL_Client | CE_NCT_SSL_Server | CE_NCT_SMIME | CE_NCT_ObjSign |
- CE_NCT_SSL_CA | CE_NCT_SMIME_CA | CE_NCT_ObjSignCA)) {
- keyUse |= CSSM_KEYUSE_VERIFY;
- }
- }
- }
- if(keyUse == 0) {
- /* Nothing found; take the default. */
- keyUse = CSSM_KEYUSE_ANY;
- }
- return keyUse;
-}
-
-/*
- * Obtain a CSSM_KEY from a decoded cert, inferring as much as we can
- * from required fields (subjectPublicKeyInfo) and extensions (for
- * KeyUse).
- */
-CSSM_KEY_PTR DecodedCert::extractCSSMKey(
- Allocator &alloc) const
-{
- const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo =
- mCert.tbs.subjectPublicKeyInfo;
- return CL_extractCSSMKeyNSS(keyInfo, alloc, this);
-}
-