2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // Session_CSP.cpp - CSR-related session functions.
23 #include "AppleX509CLSession.h"
24 #include "DecodedCert.h"
25 #include "clNameUtils.h"
26 #include "clNssUtils.h"
27 #include "cldebugging.h"
28 #include "CSPAttacher.h"
29 #include "clNssUtils.h"
30 #include <Security/oidsattr.h>
31 #include <Security/oidscert.h>
32 #include <Security/cssmapple.h>
33 #include <Security/cssmerrno.h>
34 #include <SecurityNssAsn1/csrTemplates.h>
37 * Generate a DER-encoded CSR.
39 void AppleX509CLSession::generateCsr(
40 CSSM_CC_HANDLE CCHandle
,
41 const CSSM_APPLE_CL_CSR_REQUEST
*csrReq
,
42 CSSM_DATA_PTR
&csrPtr
)
45 * We use the full NSSCertRequest here; we encode the
46 * NSSCertRequestInfo component separately to calculate
47 * its signature, then we encode the whole NSSCertRequest
48 * after dropping in the signature and SignatureAlgorithmIdentifier.
50 NSSCertRequest certReq
;
51 NSSCertRequestInfo
&reqInfo
= certReq
.reqInfo
;
54 memset(&certReq
, 0, sizeof(certReq
));
57 * Step 1: convert CSSM_APPLE_CL_CSR_REQUEST to CertificationRequestInfo.
58 * All allocs via local arena pool.
61 ArenaAllocator
alloc(coder
);
62 clIntToData(0, reqInfo
.version
, alloc
);
64 /* subject Name, required */
65 if(csrReq
->subjectNameX509
== NULL
) {
66 CssmError::throwMe(CSSMERR_CL_INVALID_POINTER
);
68 CL_cssmNameToNss(*csrReq
->subjectNameX509
, reqInfo
.subject
, coder
);
70 /* key --> CSSM_X509_SUBJECT_PUBLIC_KEY_INFO */
71 CL_CSSMKeyToSubjPubKeyInfoNSS(*csrReq
->subjectPublicKey
,
72 reqInfo
.subjectPublicKeyInfo
, coder
);
74 /* attributes - see sm_x501if - we support one, CSSMOID_ChallengePassword,
75 * as a printable string */
76 if(csrReq
->challengeString
) {
77 /* alloc a NULL_terminated array of NSS_Attribute pointers */
78 reqInfo
.attributes
= (NSS_Attribute
**)coder
.malloc(2 * sizeof(NSS_Attribute
*));
79 reqInfo
.attributes
[1] = NULL
;
81 /* alloc one NSS_Attribute */
82 reqInfo
.attributes
[0] = (NSS_Attribute
*)coder
.malloc(sizeof(NSS_Attribute
));
83 NSS_Attribute
*attr
= reqInfo
.attributes
[0];
84 memset(attr
, 0, sizeof(NSS_Attribute
));
86 /* NULL_terminated array of attrValues */
87 attr
->attrValue
= (CSSM_DATA
**)coder
.malloc(2 * sizeof(CSSM_DATA
*));
88 attr
->attrValue
[1] = NULL
;
90 /* one value - we're almost there */
91 attr
->attrValue
[0] = (CSSM_DATA
*)coder
.malloc(sizeof(CSSM_DATA
));
93 /* attrType is an OID, temp, use static OID */
94 attr
->attrType
= CSSMOID_ChallengePassword
;
96 /* one value, spec'd as AsnAny, we have to encode first. */
98 strData
.Data
= (uint8
*)csrReq
->challengeString
;
99 strData
.Length
= strlen(csrReq
->challengeString
);
100 prtn
= coder
.encodeItem(&strData
, SEC_PrintableStringTemplate
,
101 *attr
->attrValue
[0]);
103 clErrorLog("generateCsr: error encoding challengeString\n");
104 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
109 * Step 2: DER-encode the NSSCertRequestInfo prior to signing.
111 CSSM_DATA encReqInfo
;
112 prtn
= coder
.encodeItem(&reqInfo
, NSS_CertRequestInfoTemplate
, encReqInfo
);
114 clErrorLog("generateCsr: error encoding CertRequestInfo\n");
115 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
119 * Step 3: sign the encoded NSSCertRequestInfo.
121 CssmAutoData
sig(*this);
122 CssmData
&infoData
= CssmData::overlay(encReqInfo
);
123 signData(CCHandle
, infoData
, sig
);
126 * Step 4: finish up NSSCertRequest - signatureAlgorithm, signature
128 certReq
.signatureAlgorithm
.algorithm
= csrReq
->signatureOid
;
129 /* FIXME - for now assume NULL alg params */
130 CL_nullAlgParams(certReq
.signatureAlgorithm
);
131 certReq
.signature
.Data
= (uint8
*)sig
.data();
132 certReq
.signature
.Length
= sig
.length() * 8;
135 * Step 5: DER-encode the finished NSSCertRequest into app space.
137 CssmAutoData
encCsr(*this);
138 prtn
= SecNssEncodeItemOdata(&certReq
, NSS_CertRequestTemplate
, encCsr
);
140 clErrorLog("generateCsr: error encoding CertRequestInfo\n");
141 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
144 /* TBD - enc64 the result, when we have this much working */
145 csrPtr
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
146 csrPtr
->Data
= (uint8
*)encCsr
.data();
147 csrPtr
->Length
= encCsr
.length();
152 * Verify CSR with its own public key.
154 void AppleX509CLSession::verifyCsr(
155 const CSSM_DATA
*csrPtr
)
158 * 1. Extract the public key from the CSR. We do this by decoding
159 * the whole thing and getting a CSSM_KEY from the
160 * SubjectPublicKeyInfo.
162 NSSCertRequest certReq
;
166 memset(&certReq
, 0, sizeof(certReq
));
167 prtn
= coder
.decodeItem(*csrPtr
, NSS_CertRequestTemplate
, &certReq
);
169 CssmError::throwMe(CSSMERR_CL_INVALID_DATA
);
172 NSSCertRequestInfo
&reqInfo
= certReq
.reqInfo
;
173 CSSM_KEY_PTR cssmKey
= CL_extractCSSMKeyNSS(reqInfo
.subjectPublicKeyInfo
,
175 NULL
); // no DecodedCert
178 * 2. Obtain signature algorithm and parameters.
180 CSSM_X509_ALGORITHM_IDENTIFIER sigAlgId
= certReq
.signatureAlgorithm
;
181 CSSM_ALGORITHMS vfyAlg
= CL_oidToAlg(sigAlgId
.algorithm
);
184 * 3. Extract the raw bits to be verified and the signature. We
185 * decode the CSR as a CertificationRequestSigned for this, which
186 * avoids the decode of the CertificationRequestInfo.
188 NSS_SignedCertRequest certReqSigned
;
189 memset(&certReqSigned
, 0, sizeof(certReqSigned
));
190 prtn
= coder
.decodeItem(*csrPtr
, NSS_SignedCertRequestTemplate
, &certReqSigned
);
192 CssmError::throwMe(CSSMERR_CL_INVALID_DATA
);
195 CSSM_DATA sigBytes
= certReqSigned
.signature
;
196 sigBytes
.Length
= (sigBytes
.Length
+ 7 ) / 8;
197 CssmData
&sigCdata
= CssmData::overlay(sigBytes
);
198 CssmData
&toVerify
= CssmData::overlay(certReqSigned
.certRequestBlob
);
201 * 4. Attach to CSP, cook up signature context, verify signature.
203 CSSM_CSP_HANDLE cspHand
= getGlobalCspHand(true);
205 CSSM_CC_HANDLE ccHand
;
206 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
208 NULL
, // Access Creds
212 CssmError::throwMe(crtn
);
214 verifyData(ccHand
, toVerify
, sigCdata
);
215 CL_freeCSSMKey(cssmKey
, *this);