]> git.saurik.com Git - apple/security.git/blob - AppleX509CL/Session_CSR.cpp
Security-54.1.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 "SnaccUtils.h"
26 #include "cldebugging.h"
27 #include "CSPAttacher.h"
28 #include "CertBuilder.h"
29 #include <Security/oidscert.h>
30 #include <Security/cssmapple.h>
31 #include <Security/cssmerrno.h>
32 #include <Security/cdsaUtils.h>
33 #include <Security/pkcs10.h>
34
35 /*
36 * Generate a DER-encoded CSR.
37 */
38 void AppleX509CLSession::generateCsr(
39 CSSM_CC_HANDLE CCHandle,
40 const CSSM_APPLE_CL_CSR_REQUEST *csrReq,
41 CSSM_DATA_PTR &csrPtr)
42 {
43 /*
44 * We use the full CertificationRequest here; we encode the
45 * CertificationRequestInfo component separately to calculate
46 * its signature, then we encode the whole CertificationRequest
47 * after dropping in the signature and SignatureAlgorithmIdentifier.
48 *
49 * CertificationRequestInfo, CertificationRequest from pkcs10
50 */
51 CertificationRequest certReq;
52 CertificationRequestInfo *reqInfo = new CertificationRequestInfo;
53 certReq.certificationRequestInfo = reqInfo;
54
55 /*
56 * Step 1: convert CSSM_APPLE_CL_CSR_REQUEST to CertificationRequestInfo.
57 */
58 reqInfo->version.Set(0);
59
60 /* subject Name */
61 NameBuilder *subject = new NameBuilder;
62 reqInfo->subject = subject;
63 subject->addX509Name(csrReq->subjectNameX509);
64
65 /* SubjectPublicKeyInfo, AlgorithmIdentifier from sm_x509af */
66 SubjectPublicKeyInfo *snaccKeyInfo = new SubjectPublicKeyInfo;
67 reqInfo->subjectPublicKeyInfo = snaccKeyInfo;
68 AlgorithmIdentifier *snaccAlgId = new AlgorithmIdentifier;
69 snaccKeyInfo->algorithm = snaccAlgId;
70 CL_cssmAlgToSnaccOid(csrReq->subjectPublicKey->KeyHeader.AlgorithmId,
71 snaccAlgId->algorithm);
72 /* FIXME - for now assume NULL alg params */
73 CL_nullAlgParams(*snaccAlgId);
74
75 /* actual public key blob - AsnBits */
76 snaccKeyInfo->subjectPublicKey.Set(reinterpret_cast<char *>
77 (csrReq->subjectPublicKey->KeyData.Data),
78 csrReq->subjectPublicKey->KeyData.Length * 8);
79
80 /* attributes - see sm_x501if - we support one, CSSMOID_ChallengePassword,
81 * as a printable string */
82 if(csrReq->challengeString) {
83 Attribute *attr = reqInfo->attributes.Append();
84 /* attr->type is an OID */
85 attr->type.Set(challengePassword_arc);
86 /* one value, spec'd as AsnAny, we have to encode first. */
87 PrintableString snaccStr(csrReq->challengeString);
88 CssmAutoData encChallenge(*this);
89 SC_encodeAsnObj(snaccStr, encChallenge,
90 strlen(csrReq->challengeString) + 32);
91 /* AttributeValue is an AsnAny as far as SNACC is concerned */
92 AttributeValue *av = attr->values.Append();
93 CSM_Buffer *cbuf = new CSM_Buffer((char *)encChallenge.data(),
94 encChallenge.length());
95 av->value = cbuf;
96 }
97
98 /*
99 * Step 2: DER-encode the CertificationRequestInfo.
100 */
101 CssmAutoData encReqInfo(*this);
102 SC_encodeAsnObj(*reqInfo, encReqInfo, 8 * 1024); // totally wild guess
103
104 /*
105 * Step 3: sign the encoded CertificationRequestInfo.
106 */
107 CssmAutoData sig(*this);
108 signData(CCHandle, encReqInfo, sig);
109
110 /*
111 * Step 4: finish up CertificationRequest - signatureAlgorithm, signature
112 */
113 certReq.signatureAlgorithm = new SignatureAlgorithmIdentifier;
114 certReq.signatureAlgorithm->algorithm.Set(reinterpret_cast<char *>(
115 csrReq->signatureOid.Data), csrReq->signatureOid.Length);
116 /* FIXME - for now assume NULL alg params */
117 CL_nullAlgParams(*certReq.signatureAlgorithm);
118 certReq.signature.Set((char *)sig.data(), sig.length() * 8);
119
120 /*
121 * Step 5: DER-encode the finished CertificationRequestSigned.
122 */
123 CssmAutoData encCsr(*this);
124 SC_encodeAsnObj(certReq, encCsr,
125 encReqInfo.length() + // size of the thing we signed
126 sig.length() + // size of signature
127 100); // sigAlgId plus encoding overhead
128
129 /* TBD - enc64 the result, when we have this much working */
130 csrPtr = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
131 csrPtr->Data = (uint8 *)malloc(encCsr.length());
132 csrPtr->Length = encCsr.length();
133 memmove(csrPtr->Data, encCsr.data(), encCsr.length());
134 }
135
136 /*
137 * Verify CSR with its own public key.
138 */
139 void AppleX509CLSession::verifyCsr(
140 const CSSM_DATA *csrPtr)
141 {
142 /*
143 * 1. Extract the public key from the CSR. We do this by decoding
144 * the whole thing and getting a CSSM_KEY from the
145 * SubjectPublicKeyInfo.
146 */
147 CertificationRequest certReq;
148 const CssmData &csrEnc = CssmData::overlay(*csrPtr);
149 SC_decodeAsnObj(csrEnc, certReq);
150 CertificationRequestInfo *certReqInfo = certReq.certificationRequestInfo;
151 if(certReqInfo == NULL) {
152 CssmError::throwMe(CSSMERR_CL_INVALID_DATA);
153 }
154 CSSM_KEY_PTR cssmKey = CL_extractCSSMKey(*certReqInfo->subjectPublicKeyInfo,
155 *this, // alloc
156 NULL); // no DecodedCert
157
158 /*
159 * 2. Obtain signature algorithm and parameters.
160 */
161 SignatureAlgorithmIdentifier *snaccAlgId = certReq.signatureAlgorithm;
162 if(snaccAlgId == NULL) {
163 CssmError::throwMe(CSSMERR_CL_INVALID_DATA);
164 }
165 CSSM_ALGORITHMS vfyAlg = CL_snaccOidToCssmAlg(snaccAlgId->algorithm);
166
167 /*
168 * 3. Extract the raw bits to be verified and the signature. We
169 * decode the CSR as a CertificationRequestSigned for this, which
170 * avoids the decode of the CertificationRequestInfo.
171 */
172 CertificationRequestSigned certReqSigned;
173 SC_decodeAsnObj(csrEnc, certReqSigned);
174
175 CSM_Buffer *cbuf = certReqSigned.certificationRequestInfo.value;
176 char *cbufData = const_cast<char *>(cbuf->Access());
177 CssmData toVerify(cbufData, cbuf->Length());
178 AsnBits sigBits = certReqSigned.signature;
179 size_t sigBytes = (sigBits.BitLen() + 7) / 8;
180 CssmData sig(const_cast<char *>(sigBits.BitOcts()), sigBytes);
181
182 /*
183 * 4. Attach to CSP, cook up signature context, verify signature.
184 */
185 CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true);
186 CSSM_RETURN crtn;
187 CSSM_CC_HANDLE ccHand;
188 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
189 vfyAlg,
190 NULL, // Access Creds
191 cssmKey,
192 &ccHand);
193 if(crtn) {
194 CssmError::throwMe(crtn);
195 }
196 verifyData(ccHand, toVerify, sig);
197 CL_freeCSSMKey(cssmKey, *this);
198 }