]>
git.saurik.com Git - apple/security.git/blob - SecureTransport/sslCert.cpp
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.
22 Contains: certificate request/verify messages
24 Written by: Doug Mitchell
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
29 #include "sslContext.h"
30 #include "sslHandshake.h"
31 #include "sslMemory.h"
32 #include "sslAlertMessage.h"
35 #include "sslDigests.h"
36 #include "appleCdsa.h"
42 SSLEncodeCertificate(SSLRecord
&certificate
, SSLContext
*ctx
)
50 * TBD: for client side, match Match DER-encoded acceptable DN list
51 * (ctx->acceptableDNList) to one of our certs. For now we just send
52 * what we have since we don't support multiple certs.
54 * Note this can be called with localCert==0 for client seide in TLS1;
55 * in that case we send an empty cert msg.
57 cert
= ctx
->localCert
;
58 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
59 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
60 assert((cert
!= NULL
) || (ctx
->negProtocolVersion
== TLS_Version_1_0
));
64 { totalLength
+= 3 + cert
->derCert
.length
; /* 3 for encoded length field */
69 certificate
.contentType
= SSL_RecordTypeHandshake
;
70 certificate
.protocolVersion
= ctx
->negProtocolVersion
;
71 if ((err
= SSLAllocBuffer(certificate
.contents
, totalLength
+ 7, ctx
)) != 0)
74 charPtr
= certificate
.contents
.data
;
75 *charPtr
++ = SSL_HdskCert
;
76 charPtr
= SSLEncodeInt(charPtr
, totalLength
+3, 3); /* Handshake message length */
77 charPtr
= SSLEncodeInt(charPtr
, totalLength
, 3); /* Vector length */
79 /* Root cert is first in the linked list, but has to go last,
80 * so walk list backwards */
81 for (i
= 0; i
< certCount
; ++i
)
82 { cert
= ctx
->localCert
;
83 for (j
= i
+1; j
< certCount
; ++j
)
85 charPtr
= SSLEncodeInt(charPtr
, cert
->derCert
.length
, 3);
86 memcpy(charPtr
, cert
->derCert
.data
, cert
->derCert
.length
);
87 charPtr
+= cert
->derCert
.length
;
90 assert(charPtr
== certificate
.contents
.data
+ certificate
.contents
.length
);
92 if ((ctx
->protocolSide
== SSL_ClientSide
) && (ctx
->localCert
)) {
93 /* this tells us to send a CertificateVerify msg after the
94 * client key exchange. We skip the cert vfy if we just
95 * sent an empty cert msg (i.e., we were asked for a cert
96 * but we don't have one). */
98 assert(ctx
->clientCertState
== kSSLClientCertRequested
);
99 assert(ctx
->certRequested
);
100 ctx
->clientCertState
= kSSLClientCertSent
;
106 SSLProcessCertificate(SSLBuffer message
, SSLContext
*ctx
)
108 UInt32 listLen
, certLen
;
110 SSLCertificate
*cert
;
113 listLen
= SSLDecodeInt(p
,3);
115 if (listLen
+ 3 != message
.length
) {
116 sslErrorLog("SSLProcessCertificate: length decode error 1\n");
117 return errSSLProtocol
;
121 { certLen
= SSLDecodeInt(p
,3);
123 if (listLen
< certLen
+ 3) {
124 sslErrorLog("SSLProcessCertificate: length decode error 2\n");
125 return errSSLProtocol
;
127 cert
= (SSLCertificate
*)sslMalloc(sizeof(SSLCertificate
));
131 if ((err
= SSLAllocBuffer(cert
->derCert
, certLen
, ctx
)) != 0)
135 memcpy(cert
->derCert
.data
, p
, certLen
);
137 cert
->next
= ctx
->peerCert
; /* Insert backwards; root cert
138 * will be first in linked list */
139 ctx
->peerCert
= cert
;
140 listLen
-= 3+certLen
;
142 assert(p
== message
.data
+ message
.length
&& listLen
== 0);
144 if (ctx
->peerCert
== 0) {
145 /* this *might* be OK... */
146 if((ctx
->protocolSide
== SSL_ServerSide
) &&
147 (ctx
->clientAuth
!= kAlwaysAuthenticate
)) {
149 * we tried to authenticate, client doesn't have a cert, and
150 * app doesn't require it. OK.
155 return errSSLXCertChainInvalid
;
158 if((err
= sslVerifyCertChain(ctx
, *ctx
->peerCert
)) != 0)
161 /* peer's certificate is the last one in the chain */
162 cert
= ctx
->peerCert
;
163 while (cert
->next
!= 0)
165 /* Convert its public key to CDSA format */
166 if ((err
= sslPubKeyFromCert(ctx
,
169 &ctx
->peerPubKeyCsp
)) != 0)
176 SSLEncodeCertificateRequest(SSLRecord
&request
, SSLContext
*ctx
)
179 UInt32 dnListLen
, msgLen
;
183 assert(ctx
->protocolSide
== SSL_ServerSide
);
185 dn
= ctx
->acceptableDNList
;
187 { dnListLen
+= 2 + dn
->derDN
.length
;
190 msgLen
= 1 + 1 + 2 + dnListLen
;
192 request
.contentType
= SSL_RecordTypeHandshake
;
193 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
194 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
195 request
.protocolVersion
= ctx
->negProtocolVersion
;
196 if ((err
= SSLAllocBuffer(request
.contents
, msgLen
+ 4, ctx
)) != 0)
199 charPtr
= request
.contents
.data
;
200 *charPtr
++ = SSL_HdskCertRequest
;
201 charPtr
= SSLEncodeInt(charPtr
, msgLen
, 3);
203 *charPtr
++ = 1; /* one cert type */
204 *charPtr
++ = 1; /* RSA-sign type */
205 charPtr
= SSLEncodeInt(charPtr
, dnListLen
, 2);
206 dn
= ctx
->acceptableDNList
;
208 { charPtr
= SSLEncodeInt(charPtr
, dn
->derDN
.length
, 2);
209 memcpy(charPtr
, dn
->derDN
.data
, dn
->derDN
.length
);
210 charPtr
+= dn
->derDN
.length
;
214 assert(charPtr
== request
.contents
.data
+ request
.contents
.length
);
219 SSLProcessCertificateRequest(SSLBuffer message
, SSLContext
*ctx
)
226 * Cert request only happens in during client authentication, which
227 * we don't do. We will however take this handshake msg and do
228 * nothing with the enclosed DNList. We'll send a client cert
229 * if we have one but we don't do any DNList compare.
231 if (message
.length
< 3) {
232 sslErrorLog("SSLProcessCertificateRequest: length decode error 1\n");
233 return errSSLProtocol
;
235 charPtr
= message
.data
;
236 typeCount
= *charPtr
++;
237 if (typeCount
< 1 || message
.length
< 3 + typeCount
) {
238 sslErrorLog("SSLProcessCertificateRequest: length decode error 2\n");
239 return errSSLProtocol
;
241 for (i
= 0; i
< typeCount
; i
++)
242 { if (*charPtr
++ == 1)
243 ctx
->x509Requested
= 1;
247 /* FIXME - currently untested */
254 dnListLen
= SSLDecodeInt(charPtr
, 2);
256 if (message
.length
!= 3 + typeCount
+ dnListLen
) {
257 sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n");
258 return errSSLProtocol
;
260 while (dnListLen
> 0)
261 { if (dnListLen
< 2) {
262 sslErrorLog("SSLProcessCertificateRequest: dnListLen error 1\n");
263 return errSSLProtocol
;
265 dnLen
= SSLDecodeInt(charPtr
, 2);
267 if (dnListLen
< 2 + dnLen
) {
268 sslErrorLog("SSLProcessCertificateRequest: dnListLen error 2\n");
269 return errSSLProtocol
;
271 if ((err
= SSLAllocBuffer(dnBuf
, sizeof(DNListElem
), ctx
)) != 0)
273 dn
= (DNListElem
*)dnBuf
.data
;
274 if ((err
= SSLAllocBuffer(dn
->derDN
, dnLen
, ctx
)) != 0)
275 { SSLFreeBuffer(dnBuf
, ctx
);
278 memcpy(dn
->derDN
.data
, charPtr
, dnLen
);
280 dn
->next
= ctx
->acceptableDNList
;
281 ctx
->acceptableDNList
= dn
;
282 dnListLen
-= 2 + dnLen
;
285 assert(charPtr
== message
.data
+ message
.length
);
286 #endif /* untested client-side authentication */
292 SSLEncodeCertificateVerify(SSLRecord
&certVerify
, SSLContext
*ctx
)
295 SSLBuffer hashDataBuf
, shaMsgState
, md5MsgState
;
299 certVerify
.contents
.data
= 0;
300 hashDataBuf
.data
= hashData
;
301 hashDataBuf
.length
= 36;
303 if ((err
= CloneHashState(SSLHashSHA1
, ctx
->shaState
, shaMsgState
, ctx
)) != 0)
305 if ((err
= CloneHashState(SSLHashMD5
, ctx
->md5State
, md5MsgState
, ctx
)) != 0)
307 assert(ctx
->sslTslCalls
!= NULL
);
308 if ((err
= ctx
->sslTslCalls
->computeCertVfyMac(ctx
, hashDataBuf
,
309 shaMsgState
, md5MsgState
)) != 0)
312 assert(ctx
->signingPrivKey
!= NULL
);
313 len
= sslKeyLengthInBytes(ctx
->signingPrivKey
);
315 certVerify
.contentType
= SSL_RecordTypeHandshake
;
316 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
317 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
318 certVerify
.protocolVersion
= ctx
->negProtocolVersion
;
319 if ((err
= SSLAllocBuffer(certVerify
.contents
, len
+ 6, ctx
)) != 0)
322 certVerify
.contents
.data
[0] = SSL_HdskCertVerify
;
323 SSLEncodeInt(certVerify
.contents
.data
+1, len
+2, 3);
324 SSLEncodeInt(certVerify
.contents
.data
+4, len
, 2);
326 err
= sslRsaRawSign(ctx
,
329 hashData
, // data to sign
330 36, // MD5 size + SHA1 size
331 certVerify
.contents
.data
+6, // signature destination
332 len
, // we mallocd len+6
338 assert(outputLen
== len
);
343 SSLFreeBuffer(shaMsgState
, ctx
);
344 SSLFreeBuffer(md5MsgState
, ctx
);
350 SSLProcessCertificateVerify(SSLBuffer message
, SSLContext
*ctx
)
354 SSLBuffer hashDataBuf
, shaMsgState
, md5MsgState
;
355 unsigned int publicModulusLen
;
357 shaMsgState
.data
= 0;
358 md5MsgState
.data
= 0;
360 if (message
.length
< 2) {
361 sslErrorLog("SSLProcessCertificateVerify: msg len error\n");
362 return errSSLProtocol
;
365 signatureLen
= (UInt16
)SSLDecodeInt(message
.data
, 2);
366 if (message
.length
!= (unsigned)(2 + signatureLen
)) {
367 sslErrorLog("SSLProcessCertificateVerify: sig len error 1\n");
368 return errSSLProtocol
;
371 assert(ctx
->peerPubKey
!= NULL
);
372 publicModulusLen
= sslKeyLengthInBytes(ctx
->peerPubKey
);
374 if (signatureLen
!= publicModulusLen
) {
375 sslErrorLog("SSLProcessCertificateVerify: sig len error 2\n");
376 return errSSLProtocol
;
378 hashDataBuf
.data
= hashData
;
379 hashDataBuf
.length
= 36;
381 if ((err
= CloneHashState(SSLHashSHA1
, ctx
->shaState
, shaMsgState
, ctx
)) != 0)
383 if ((err
= CloneHashState(SSLHashMD5
, ctx
->md5State
, md5MsgState
, ctx
)) != 0)
385 assert(ctx
->sslTslCalls
!= NULL
);
386 if ((err
= ctx
->sslTslCalls
->computeCertVfyMac(ctx
, hashDataBuf
,
387 shaMsgState
, md5MsgState
)) != 0)
391 * The CSP does the decrypt & compare for us in one shot
393 err
= sslRsaRawVerify(ctx
,
395 ctx
->peerPubKeyCsp
, // FIXME - maybe we just use cspHand?
396 hashData
, // data to verify
398 message
.data
+ 2, // signature
406 SSLFreeBuffer(shaMsgState
, ctx
);
407 SSLFreeBuffer(md5MsgState
, ctx
);