1/*
2 * Copyright (c) 2008-2009,2012-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * SecOCSPResponse.c - Wrapper to decode ocsp responses.
26 */
27
28#include <securityd/SecOCSPResponse.h>
29
30#include <asl.h>
31#include <AssertMacros.h>
32#include <CommonCrypto/CommonDigest.h>
33#include <Security/SecCertificateInternal.h>
34#include <Security/SecFramework.h>
35#include <Security/SecKeyPriv.h>
36#include <security_asn1/SecAsn1Coder.h>
37#include <security_asn1/ocspTemplates.h>
38#include <security_asn1/oidsalg.h>
39#include <security_asn1/oidsocsp.h>
40#include <stdlib.h>
41#include "SecInternal.h"
42#include <utilities/SecCFWrappers.h>
43
44#define ocspdErrorLog(args, ...)     secerror(args, ## __VA_ARGS__)
45#define ocspdHttpDebug(args...)     secdebug("ocspdHttp", ## args)
46#define ocspdDebug(args...)     secdebug("ocsp", ## args)
47
48
49/*
50   OCSPResponse ::= SEQUENCE {
51      responseStatus         OCSPResponseStatus,
52      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
53
54   OCSPResponseStatus ::= ENUMERATED {
55       successful            (0),  --Response has valid confirmations
56       malformedRequest      (1),  --Illegal confirmation request
57       internalError         (2),  --Internal error in issuer
58       tryLater              (3),  --Try again later
59                                   --(4) is not used
60       sigRequired           (5),  --Must sign the request
61       unauthorized          (6)   --Request unauthorized
62   }
63
64   ResponseBytes ::=       SEQUENCE {
65       responseType   OBJECT IDENTIFIER,
66       response       OCTET STRING }
67
68   id-pkix-ocsp           OBJECT IDENTIFIER ::= { id-ad-ocsp }
69   id-pkix-ocsp-basic     OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 }
70
71   The value for response SHALL be the DER encoding of
72   BasicOCSPResponse.
73
74   BasicOCSPResponse       ::= SEQUENCE {
75      tbsResponseData      ResponseData,
76      signatureAlgorithm   AlgorithmIdentifier,
77      signature            BIT STRING,
78      certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
79
80   The value for signature SHALL be computed on the hash of the DER
81   encoding ResponseData.
82
83   ResponseData ::= SEQUENCE {
84      version              [0] EXPLICIT Version DEFAULT v1,
85      responderID              ResponderID,
86      producedAt               GeneralizedTime,
87      responses                SEQUENCE OF SingleResponse,
88      responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
89
90   ResponderID ::= CHOICE {
91      byName               [1] Name,
92      byKey                [2] KeyHash }
93
94   KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
95   (excluding the tag and length fields)
96
97   SingleResponse ::= SEQUENCE {
98      certID                       CertID,
99      certStatus                   CertStatus,
100      thisUpdate                   GeneralizedTime,
101      nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
102      singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
103
104   CertStatus ::= CHOICE {
105       good        [0]     IMPLICIT NULL,
106       revoked     [1]     IMPLICIT RevokedInfo,
107       unknown     [2]     IMPLICIT UnknownInfo }
108
109   RevokedInfo ::= SEQUENCE {
110       revocationTime              GeneralizedTime,
111       revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
112
113   UnknownInfo ::= NULL -- this can be replaced with an enumeration
114*/
115
116static CFAbsoluteTime genTimeToCFAbsTime(const SecAsn1Item *datetime)
117{
118    return SecAbsoluteTimeFromDateContent(SEC_ASN1_GENERALIZED_TIME,
119        datetime->Data, datetime->Length);
120}
121
122void SecOCSPSingleResponseDestroy(SecOCSPSingleResponseRef this) {
123    free(this);
124}
125
126static SecOCSPSingleResponseRef SecOCSPSingleResponseCreate(
127    SecAsn1OCSPSingleResponse *resp, SecAsn1CoderRef coder) {
128	assert(resp != NULL);
129    SecOCSPSingleResponseRef this;
130    require(this = (SecOCSPSingleResponseRef)
131        malloc(sizeof(struct __SecOCSPSingleResponse)), errOut);
132    this->certStatus = CS_NotParsed;
133	this->thisUpdate = NULL_TIME;
134	this->nextUpdate = NULL_TIME;
135	this->revokedTime = NULL_TIME;
136	this->crlReason = kSecRevocationReasonUndetermined;
137	//this->extensions = NULL;
138
139	if ((resp->certStatus.Data == NULL) || (resp->certStatus.Length == 0)) {
140		ocspdErrorLog("OCSPSingleResponse: bad certStatus");
141        goto errOut;
142	}
143	this->certStatus = (SecAsn1OCSPCertStatusTag)(resp->certStatus.Data[0] & SEC_ASN1_TAGNUM_MASK);
144	if (this->certStatus == CS_Revoked) {
145		/* Decode further to get SecAsn1OCSPRevokedInfo */
146		SecAsn1OCSPCertStatus certStatus;
147		memset(&certStatus, 0, sizeof(certStatus));
148		if (SecAsn1DecodeData(coder, &resp->certStatus,
149				kSecAsn1OCSPCertStatusRevokedTemplate, &certStatus)) {
150			ocspdErrorLog("OCSPSingleResponse: err decoding certStatus");
151            goto errOut;
152		}
153		SecAsn1OCSPRevokedInfo *revokedInfo = certStatus.revokedInfo;
154		if (revokedInfo != NULL) {
155			/* Treat this as optional even for CS_Revoked */
156			this->revokedTime = genTimeToCFAbsTime(&revokedInfo->revocationTime);
157			const SecAsn1Item *revReason = revokedInfo->revocationReason;
158			if((revReason != NULL) &&
159			   (revReason->Data != NULL) &&
160			   (revReason->Length != 0)) {
161			   this->crlReason = revReason->Data[0];
162			}
163		}
164	}
165	this->thisUpdate = genTimeToCFAbsTime(&resp->thisUpdate);
166	if (resp->nextUpdate != NULL) {
167		this->nextUpdate = genTimeToCFAbsTime(resp->nextUpdate);
168	}
169	//mExtensions = new OCSPExtensions(resp->singleExtensions);
170	ocspdDebug("status %d reason %d", (int)this->certStatus,
171		(int)this->crlReason);
172    return this;
173errOut:
174    if (this)
175        SecOCSPSingleResponseDestroy(this);
176    return NULL;
177}
178
179#define LEEWAY (4500.0)
180
181/* Calculate temporal validity; set latestNextUpdate and expireTime. Only
182   called from SecOCSPResponseCreate. Returns true if valid, else returns
183   false. */
184static bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this,
185    CFTimeInterval maxAge, CFTimeInterval defaultTTL)
186{
187    bool ok = false;
188	this->latestNextUpdate = NULL_TIME;
189	CFAbsoluteTime now = this->verifyTime = CFAbsoluteTimeGetCurrent();
190    CFStringRef hexResp = CFDataCopyHexString(this->data);
191
192    if (this->producedAt > now + LEEWAY) {
193        ocspdErrorLog("OCSPResponse: producedAt more than 1:15 from now %@", hexResp);
194        goto exit;
195    }
196
197    /* Make this->latestNextUpdate be the date farthest in the future
198       of any of the singleResponses nextUpdate fields. */
199    SecAsn1OCSPSingleResponse **responses;
200    for (responses = this->responseData.responses; *responses; ++responses) {
201		SecAsn1OCSPSingleResponse *resp = *responses;
202
203		/* thisUpdate later than 'now' invalidates the whole response. */
204		CFAbsoluteTime thisUpdate = genTimeToCFAbsTime(&resp->thisUpdate);
205		if (thisUpdate > now + LEEWAY) {
206			ocspdErrorLog("OCSPResponse: thisUpdate more than 1:15 from now %@", hexResp);
207            goto exit;
208		}
209
210		/* Keep track of latest nextUpdate. */
211		if (resp->nextUpdate != NULL) {
212			CFAbsoluteTime nextUpdate = genTimeToCFAbsTime(resp->nextUpdate);
213			if (nextUpdate > this->latestNextUpdate) {
214				this->latestNextUpdate = nextUpdate;
215			}
216		}
217        else {
218            /* RFC 5019 section 2.2.4 states on nextUpdate:
219                 Responders MUST always include this value to aid in
220                 response caching.  See Section 6 for additional
221                 information on caching.
222            */
223			ocspdErrorLog("OCSPResponse: nextUpdate not present %@", hexResp);
224#ifdef STRICT_RFC5019
225            goto exit;
226#endif
227        }
228	}
229
230    /* Now that we have this->latestNextUpdate, we figure out the latest
231       date at which we will expire this response from our cache.  To comply
232       with rfc5019s:
233
2346.1.  Caching at the Client
235
236   To minimize bandwidth usage, clients MUST locally cache authoritative
237   OCSP responses (i.e., a response with a signature that has been
238   successfully validated and that indicate an OCSPResponseStatus of
239   'successful').
240
241   Most OCSP clients will send OCSPRequests at or near the nextUpdate
242   time (when a cached response expires).  To avoid large spikes in
243   responder load that might occur when many clients refresh cached
244   responses for a popular certificate, responders MAY indicate when the
245   client should fetch an updated OCSP response by using the cache-
246   control:max-age directive.  Clients SHOULD fetch the updated OCSP
247   Response on or after the max-age time.  To ensure that clients
248   receive an updated OCSP response, OCSP responders MUST refresh the
249   OCSP response before the max-age time.
250
2516.2 [...]
252
253       we need to take the cache-control:max-age directive into account.
254
255       The way the code below is written we ignore a max-age=0 in the
256       http header.  Since a value of 0 (NULL_TIME) also means there
257       was no max-age in the header. This seems ok since that would imply
258       no-cache so we also ignore negative values for the same reason,
259       instead we'll expire whenever this->latestNextUpdate tells us to,
260       which is the signed value if max-age is too low, since we don't
261       want to refetch multilple times for a single page load in a browser. */
262	if (this->latestNextUpdate == NULL_TIME) {
263        /* See comment above on RFC 5019 section 2.2.4. */
264		/* Absolute expire time = current time plus defaultTTL */
265		this->expireTime = now + defaultTTL;
266	} else if (this->latestNextUpdate < now - LEEWAY) {
267        ocspdErrorLog("OCSPResponse: latestNextUpdate more than 1:15 ago %@", hexResp);
268        goto exit;
269    } else if (maxAge > 0) {
270        /* Beware of double overflows such as:
271
272               now + maxAge < this->latestNextUpdate
273
274           in the math below since an attacker could create any positive
275           value for maxAge. */
276        if (maxAge < this->latestNextUpdate - now) {
277            /* maxAge header wants us to expire the cache entry sooner than
278               nextUpdate would allow, to balance server load. */
279            this->expireTime = now + maxAge;
280        } else {
281            /* maxAge http header attempting to make us cache the response
282               longer than it's valid for, bad http header! Ignoring you. */
283            ocspdErrorLog("OCSPResponse: now + maxAge > latestNextUpdate,"
284                " using latestNextUpdate %@", hexResp);
285            this->expireTime = this->latestNextUpdate;
286        }
287	} else {
288        /* No maxAge provided, just use latestNextUpdate. */
289		this->expireTime = this->latestNextUpdate;
290    }
291
292    ok = true;
293exit:
294    CFReleaseSafe(hexResp);
295	return ok;
296}
297
298SecOCSPResponseRef SecOCSPResponseCreate(CFDataRef ocspResponse,
299    CFTimeInterval maxAge) {
300    CFStringRef hexResp = CFDataCopyHexString(ocspResponse);
301	SecAsn1OCSPResponse topResp = {};
302    SecOCSPResponseRef this;
303
304    require(this = (SecOCSPResponseRef)calloc(1, sizeof(struct __SecOCSPResponse)),
305        errOut);
306    require_noerr(SecAsn1CoderCreate(&this->coder), errOut);
307
308    this->data = ocspResponse;
309    CFRetain(ocspResponse);
310
311    SecAsn1Item resp;
312    resp.Length = CFDataGetLength(ocspResponse);
313    resp.Data = (uint8_t *)CFDataGetBytePtr(ocspResponse);
314	if (SecAsn1DecodeData(this->coder, &resp, kSecAsn1OCSPResponseTemplate,
315        &topResp)) {
316		ocspdErrorLog("OCSPResponse: decode failure at top level %@", hexResp);
317	}
318	/* remainder is valid only on RS_Success */
319	if ((topResp.responseStatus.Data == NULL) ||
320	   (topResp.responseStatus.Length == 0)) {
321		ocspdErrorLog("OCSPResponse: no responseStatus %@", hexResp);
322        goto errOut;
323	}
324    this->responseStatus = topResp.responseStatus.Data[0];
325	if (this->responseStatus != kSecOCSPSuccess) {
326		secdebug("ocsp", "OCSPResponse: status: %d %@", this->responseStatus, hexResp);
327		/* not a failure of our constructor; this object is now useful, but
328		 * only for this one byte of status info */
329		goto fini;
330	}
331	if (topResp.responseBytes == NULL) {
332		/* I don't see how this can be legal on RS_Success */
333		ocspdErrorLog("OCSPResponse: empty responseBytes %@", hexResp);
334        goto errOut;
335	}
336    if (!SecAsn1OidCompare(&topResp.responseBytes->responseType,
337			&OID_PKIX_OCSP_BASIC)) {
338		ocspdErrorLog("OCSPResponse: unknown responseType %@", hexResp);
339        goto errOut;
340
341	}
342
343	/* decode the SecAsn1OCSPBasicResponse */
344	if (SecAsn1DecodeData(this->coder, &topResp.responseBytes->response,
345			kSecAsn1OCSPBasicResponseTemplate, &this->basicResponse)) {
346		ocspdErrorLog("OCSPResponse: decode failure at SecAsn1OCSPBasicResponse %@", hexResp);
347        goto errOut;
348	}
349
350	/* signature and cert evaluation done externally */
351
352	/* decode the SecAsn1OCSPResponseData */
353	if (SecAsn1DecodeData(this->coder, &this->basicResponse.tbsResponseData,
354			kSecAsn1OCSPResponseDataTemplate, &this->responseData)) {
355		ocspdErrorLog("OCSPResponse: decode failure at SecAsn1OCSPResponseData %@", hexResp);
356        goto errOut;
357	}
358    this->producedAt = genTimeToCFAbsTime(&this->responseData.producedAt);
359    if (this->producedAt == NULL_TIME) {
360		ocspdErrorLog("OCSPResponse: bad producedAt %@", hexResp);
361        goto errOut;
362    }
363
364	if (this->responseData.responderID.Data == NULL) {
365		ocspdErrorLog("OCSPResponse: bad responderID %@", hexResp);
366        goto errOut;
367	}
368
369	/* Choice processing for ResponderID */
370    this->responderIdTag = (SecAsn1OCSPResponderIDTag)
371		(this->responseData.responderID.Data[0] & SEC_ASN1_TAGNUM_MASK);
372	const SecAsn1Template *templ;
373	switch(this->responderIdTag) {
374		case RIT_Name:
375            /* @@@ Since we don't use the decoded byName value we could skip
376               decoding it but we do it anyway for validation. */
377			templ = kSecAsn1OCSPResponderIDAsNameTemplate;
378			break;
379		case RIT_Key:
380			templ = kSecAsn1OCSPResponderIDAsKeyTemplate;
381			break;
382		default:
383			ocspdErrorLog("OCSPResponse: bad responderID tag %@", hexResp);
384            goto errOut;
385	}
386	if (SecAsn1DecodeData(this->coder, &this->responseData.responderID, templ,
387        &this->responderID)) {
388		ocspdErrorLog("OCSPResponse: decode failure at responderID %@", hexResp);
389        goto errOut;
390	}
391
392    /* We should probably get the defaultTTL from the policy.
393       For now defaultTTL is hardcoded to 24 hours. */
394    CFTimeInterval defaultTTL = 24 * 60 * 60;
395	/* Check temporal validity, default TTL 24 hours. */
396    require_quiet(SecOCSPResponseCalculateValidity(this, maxAge, defaultTTL), errOut);
397
398#if 0
399	/* Individual responses looked into when we're asked for a specific one
400	   via SecOCSPResponseCopySingleResponse(). */
401	mExtensions = new OCSPExtensions(mResponseData.responseExtensions);
402#endif
403
404fini:
405    CFReleaseSafe(hexResp);
406    return this;
407errOut:
408    CFReleaseSafe(hexResp);
409    if (this) {
410        SecOCSPResponseFinalize(this);
411    }
412    return NULL;
413}
414
415CFDataRef SecOCSPResponseGetData(SecOCSPResponseRef this) {
416    return this->data;
417}
418
419SecOCSPResponseStatus SecOCSPGetResponseStatus(SecOCSPResponseRef this) {
420    return this->responseStatus;
421}
422
423CFAbsoluteTime SecOCSPResponseGetExpirationTime(SecOCSPResponseRef this) {
424    return this->expireTime;
425}
426
427CFDataRef SecOCSPResponseGetNonce(SecOCSPResponseRef this) {
428    return this->nonce;
429}
430
431CFAbsoluteTime SecOCSPResponseProducedAt(SecOCSPResponseRef this) {
432    return this->producedAt;
433}
434
435CFAbsoluteTime SecOCSPResponseVerifyTime(SecOCSPResponseRef this) {
436    return this->verifyTime;
437}
438
439CFArrayRef SecOCSPResponseCopySigners(SecOCSPResponseRef this) {
440    return NULL;
441}
442
443void SecOCSPResponseFinalize(SecOCSPResponseRef this) {
444    CFReleaseSafe(this->data);
445    CFReleaseSafe(this->nonce);
446    SecAsn1CoderRelease(this->coder);
447    free(this);
448}
449
450SecOCSPSingleResponseRef SecOCSPResponseCopySingleResponse(
451    SecOCSPResponseRef this, SecOCSPRequestRef request) {
452    SecOCSPSingleResponseRef sr = NULL;
453
454    CFDataRef issuer = SecCertificateCopyIssuerSequence(request->certificate);
455    const DERItem *publicKey = SecCertificateGetPublicKeyData(request->issuer);
456    CFDataRef serial = SecCertificateCopySerialNumber(request->certificate);
457    CFDataRef issuerNameHash = NULL;
458    CFDataRef issuerPubKeyHash = NULL;
459    SecAsn1Oid *algorithm = NULL;
460    SecAsn1Item *parameters = NULL;
461
462    /* We should probably get the defaultTTL from the policy.
463       For now defaultTTL is hardcoded to 24 hours. This is how long we trust
464       a response without a nextUpdate field.  */
465    CFTimeInterval defaultTTL = 24 * 60 * 60;
466
467    SecAsn1OCSPSingleResponse **responses;
468    for (responses = this->responseData.responses; *responses; ++responses) {
469		SecAsn1OCSPSingleResponse *resp = *responses;
470        SecAsn1OCSPCertID *certId = &resp->certID;
471        /* First check the easy part, serial number should match. */
472        if (certId->serialNumber.Length != (size_t)CFDataGetLength(serial) ||
473            memcmp(CFDataGetBytePtr(serial), certId->serialNumber.Data,
474                certId->serialNumber.Length)) {
475            /* Serial # mismatch, skip this singleResponse. */
476            continue;
477        }
478
479        /* Calcluate the issuerKey and issuerName digests using the
480           hashAlgorithm and parameters specified in the certId, if
481           they differ from the ones we already computed. */
482        if (!SecAsn1OidCompare(algorithm, &certId->algId.algorithm) ||
483            !SecAsn1OidCompare(parameters, &certId->algId.parameters)) {
484            algorithm = &certId->algId.algorithm;
485            parameters = &certId->algId.parameters;
486            CFReleaseSafe(issuerNameHash);
487            CFReleaseSafe(issuerPubKeyHash);
488            issuerNameHash = SecDigestCreate(kCFAllocatorDefault, algorithm,
489                parameters, CFDataGetBytePtr(issuer), CFDataGetLength(issuer));
490            issuerPubKeyHash = SecDigestCreate(kCFAllocatorDefault, algorithm,
491                parameters, publicKey->data, publicKey->length);
492        }
493
494        if (certId->issuerNameHash.Length == (size_t)CFDataGetLength(issuerNameHash)
495            && !memcmp(CFDataGetBytePtr(issuerNameHash),
496                certId->issuerNameHash.Data, certId->issuerNameHash.Length)
497            && certId->issuerPubKeyHash.Length == (size_t)CFDataGetLength(issuerPubKeyHash)
498            && !memcmp(CFDataGetBytePtr(issuerPubKeyHash),
499                certId->issuerPubKeyHash.Data, certId->issuerPubKeyHash.Length)) {
500
501            CFAbsoluteTime thisUpdate = genTimeToCFAbsTime(&resp->thisUpdate);
502            if (thisUpdate > this->verifyTime) {
503                ocspdErrorLog("OCSPSingleResponse: thisUpdate > now");
504                continue;
505            }
506
507            if (resp->nextUpdate == NULL) {
508                /* rfc2560 section 2.4 states: "If nextUpdate is not set, the
509                   responder is indicating that newer revocation information
510                   is available all the time".
511                   Let's ensure that thisUpdate isn't more than defaultTTL in
512                   the past then. */
513                if (this->verifyTime > thisUpdate + defaultTTL) {
514                    ocspdErrorLog("OCSPSingleResponse: no nextUpdate present "
515                        "and now > thisUpdate + defaultTTL");
516                    continue;
517                }
518            } else {
519                CFAbsoluteTime nextUpdate = genTimeToCFAbsTime(resp->nextUpdate);
520                if (this->verifyTime > nextUpdate) {
521                    ocspdErrorLog("OCSPSingleResponse: now > nextUpdate");
522                    continue;
523                }
524            }
525
526            /* resp matches the certificate in request, so let's use it. */
527            sr = SecOCSPSingleResponseCreate(resp, this->coder);
528            if (sr) {
529                ocspdDebug("found matching singleResponse");
530                break;
531            }
532        }
533	}
534
535    CFReleaseSafe(issuerPubKeyHash);
536    CFReleaseSafe(issuerNameHash);
537    CFReleaseSafe(serial);
538    CFReleaseSafe(issuer);
539
540    if (!sr) {
541        ocspdDebug("certID not found");
542    }
543
544	return sr;
545}
546
547static bool SecOCSPResponseVerifySignature(SecOCSPResponseRef this,
548    SecKeyRef key) {
549	/* Beware this->basicResponse.sig: on decode, length is in BITS */
550    return SecKeyDigestAndVerify(key, &this->basicResponse.algId,
551        this->basicResponse.tbsResponseData.Data,
552        this->basicResponse.tbsResponseData.Length,
553        this->basicResponse.sig.Data,
554        this->basicResponse.sig.Length / 8) == errSecSuccess;
555}
556
557static bool SecOCSPResponseIsIssuer(SecOCSPResponseRef this,
558    SecCertificatePathRef issuer) {
559    bool shouldBeSigner = false;
560    SecCertificateRef signer = SecCertificatePathGetCertificateAtIndex(issuer, 0);
561	if (this->responderIdTag == RIT_Name) {
562		/* Name inside response must == signer's SubjectName. */
563        CFDataRef subject = SecCertificateCopySubjectSequence(signer);
564        if (!subject) {
565			ocspdDebug("error on SecCertificateCopySubjectSequence");
566			return false;
567		}
568        if ((size_t)CFDataGetLength(subject) == this->responderID.byName.Length &&
569            !memcmp(this->responderID.byName.Data, CFDataGetBytePtr(subject),
570                this->responderID.byName.Length)) {
571			ocspdDebug("good ResponderID.byName");
572			shouldBeSigner = true;
573        } else {
574			ocspdDebug("BAD ResponderID.byName");
575		}
576        CFRelease(subject);
577    } else /* if (this->responderIdTag == RIT_Key) */ {
578		/* ResponderID.byKey must == SHA1(signer's public key) */
579        CFDataRef pubKeyDigest = SecCertificateCopyPublicKeySHA1Digest(signer);
580        if ((size_t)CFDataGetLength(pubKeyDigest) == this->responderID.byKey.Length &&
581            !memcmp(this->responderID.byKey.Data, CFDataGetBytePtr(pubKeyDigest),
582                this->responderID.byKey.Length)) {
583			ocspdDebug("good ResponderID.byKey");
584			shouldBeSigner = true;
585		} else {
586			ocspdDebug("BAD ResponderID.byKey");
587		}
588        CFRelease(pubKeyDigest);
589    }
590
591    if (shouldBeSigner) {
592        SecKeyRef key = SecCertificatePathCopyPublicKeyAtIndex(issuer, 0);
593        if (key) {
594            shouldBeSigner = SecOCSPResponseVerifySignature(this, key);
595            ocspdDebug("ocsp response signature %sok", shouldBeSigner ? "" : "not ");
596            CFRelease(key);
597        } else {
598			ocspdDebug("Failed to extract key from leaf certificate");
599            shouldBeSigner = false;
600        }
601    }
602
603    return shouldBeSigner;
604}
605
606/* Returns the SecCertificatePathRef who's leaf signed this ocspResponse if
607   we can find one and NULL if we can't find a valid signer. */
608SecCertificatePathRef SecOCSPResponseCopySigner(SecOCSPResponseRef this,
609    SecCertificatePathRef issuer) {
610    SecCertificateRef issuerCert = SecCertificatePathGetCertificateAtIndex(issuer, 0);
611    CFDataRef issuerSubject = SecCertificateGetNormalizedSubjectContent(issuerCert);
612    /* Look though any certs that came with the response and see if they were
613       both issued by the issuerPath and signed the response. */
614    SecAsn1Item **certs;
615    for (certs = this->basicResponse.certs; certs && *certs; ++certs) {
616        SecCertificateRef cert = SecCertificateCreateWithBytes(
617            kCFAllocatorDefault, (*certs)->Data, (*certs)->Length);
618        if (cert) {
619            CFDataRef certIssuer = SecCertificateGetNormalizedIssuerContent(cert);
620            if (CFEqual(issuerSubject, certIssuer)) {
621                SecCertificatePathRef signer = SecCertificatePathCopyAddingLeaf(issuer, cert);
622                CFRelease(cert);
623                if (signer) {
624                    if (SecOCSPResponseIsIssuer(this, signer)) {
625                        return signer;
626                    } else {
627                        ocspdErrorLog("ocsp response cert not signed by issuer.");
628                        CFRelease(signer);
629                    }
630                }
631            } else {
632                ocspdErrorLog("ocsp response cert issuer doesn't match issuer subject.");
633            }
634        } else {
635			ocspdErrorLog("ocsp response cert failed to parse");
636        }
637	}
638
639    /* If none of the returned certs work, try the issuer of the certificate
640       being checked directly. */
641    if (SecOCSPResponseIsIssuer(this, issuer)) {
642        CFRetain(issuer);
643        return issuer;
644    }
645
646    /* We couldn't find who signed this ocspResponse, give up. */
647    return NULL;
648}
649