]> git.saurik.com Git - apple/security.git/blob - AppleX509CL/Session_CSR.cpp
Security-179.tar.gz
[apple/security.git] / AppleX509CL / Session_CSR.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // Session_CSP.cpp - CSR-related session functions.
21 //
22
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>
35
36 /*
37 * Generate a DER-encoded CSR.
38 */
39 void AppleX509CLSession::generateCsr(
40 CSSM_CC_HANDLE CCHandle,
41 const CSSM_APPLE_CL_CSR_REQUEST *csrReq,
42 CSSM_DATA_PTR &csrPtr)
43 {
44 /*
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.
49 */
50 NSSCertRequest certReq;
51 NSSCertRequestInfo &reqInfo = certReq.reqInfo;
52 PRErrorCode prtn;
53
54 memset(&certReq, 0, sizeof(certReq));
55
56 /*
57 * Step 1: convert CSSM_APPLE_CL_CSR_REQUEST to CertificationRequestInfo.
58 * All allocs via local arena pool.
59 */
60 SecNssCoder coder;
61 ArenaAllocator alloc(coder);
62 clIntToData(0, reqInfo.version, alloc);
63
64 /* subject Name, required */
65 if(csrReq->subjectNameX509 == NULL) {
66 CssmError::throwMe(CSSMERR_CL_INVALID_POINTER);
67 }
68 CL_cssmNameToNss(*csrReq->subjectNameX509, reqInfo.subject, coder);
69
70 /* key --> CSSM_X509_SUBJECT_PUBLIC_KEY_INFO */
71 CL_CSSMKeyToSubjPubKeyInfoNSS(*csrReq->subjectPublicKey,
72 reqInfo.subjectPublicKeyInfo, coder);
73
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;
80
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));
85
86 /* NULL_terminated array of attrValues */
87 attr->attrValue = (CSSM_DATA **)coder.malloc(2 * sizeof(CSSM_DATA *));
88 attr->attrValue[1] = NULL;
89
90 /* one value - we're almost there */
91 attr->attrValue[0] = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
92
93 /* attrType is an OID, temp, use static OID */
94 attr->attrType = CSSMOID_ChallengePassword;
95
96 /* one value, spec'd as AsnAny, we have to encode first. */
97 CSSM_DATA strData;
98 strData.Data = (uint8 *)csrReq->challengeString;
99 strData.Length = strlen(csrReq->challengeString);
100 prtn = coder.encodeItem(&strData, SEC_PrintableStringTemplate,
101 *attr->attrValue[0]);
102 if(prtn) {
103 clErrorLog("generateCsr: error encoding challengeString\n");
104 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
105 }
106 }
107
108 /*
109 * Step 2: DER-encode the NSSCertRequestInfo prior to signing.
110 */
111 CSSM_DATA encReqInfo;
112 prtn = coder.encodeItem(&reqInfo, NSS_CertRequestInfoTemplate, encReqInfo);
113 if(prtn) {
114 clErrorLog("generateCsr: error encoding CertRequestInfo\n");
115 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
116 }
117
118 /*
119 * Step 3: sign the encoded NSSCertRequestInfo.
120 */
121 CssmAutoData sig(*this);
122 CssmData &infoData = CssmData::overlay(encReqInfo);
123 signData(CCHandle, infoData, sig);
124
125 /*
126 * Step 4: finish up NSSCertRequest - signatureAlgorithm, signature
127 */
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;
133
134 /*
135 * Step 5: DER-encode the finished NSSCertRequest into app space.
136 */
137 CssmAutoData encCsr(*this);
138 prtn = SecNssEncodeItemOdata(&certReq, NSS_CertRequestTemplate, encCsr);
139 if(prtn) {
140 clErrorLog("generateCsr: error encoding CertRequestInfo\n");
141 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
142 }
143
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();
148 encCsr.release();
149 }
150
151 /*
152 * Verify CSR with its own public key.
153 */
154 void AppleX509CLSession::verifyCsr(
155 const CSSM_DATA *csrPtr)
156 {
157 /*
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.
161 */
162 NSSCertRequest certReq;
163 SecNssCoder coder;
164 PRErrorCode prtn;
165
166 memset(&certReq, 0, sizeof(certReq));
167 prtn = coder.decodeItem(*csrPtr, NSS_CertRequestTemplate, &certReq);
168 if(prtn) {
169 CssmError::throwMe(CSSMERR_CL_INVALID_DATA);
170 }
171
172 NSSCertRequestInfo &reqInfo = certReq.reqInfo;
173 CSSM_KEY_PTR cssmKey = CL_extractCSSMKeyNSS(reqInfo.subjectPublicKeyInfo,
174 *this, // alloc
175 NULL); // no DecodedCert
176
177 /*
178 * 2. Obtain signature algorithm and parameters.
179 */
180 CSSM_X509_ALGORITHM_IDENTIFIER sigAlgId = certReq.signatureAlgorithm;
181 CSSM_ALGORITHMS vfyAlg = CL_oidToAlg(sigAlgId.algorithm);
182
183 /*
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.
187 */
188 NSS_SignedCertRequest certReqSigned;
189 memset(&certReqSigned, 0, sizeof(certReqSigned));
190 prtn = coder.decodeItem(*csrPtr, NSS_SignedCertRequestTemplate, &certReqSigned);
191 if(prtn) {
192 CssmError::throwMe(CSSMERR_CL_INVALID_DATA);
193 }
194
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);
199
200 /*
201 * 4. Attach to CSP, cook up signature context, verify signature.
202 */
203 CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true);
204 CSSM_RETURN crtn;
205 CSSM_CC_HANDLE ccHand;
206 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
207 vfyAlg,
208 NULL, // Access Creds
209 cssmKey,
210 &ccHand);
211 if(crtn) {
212 CssmError::throwMe(crtn);
213 }
214 verifyData(ccHand, toVerify, sigCdata);
215 CL_freeCSSMKey(cssmKey, *this);
216 }
217