mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 04:17:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
48
security/nss/lib/certhigh/Makefile
Normal file
48
security/nss/lib/certhigh/Makefile
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#! gmake
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
-include config.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
1204
security/nss/lib/certhigh/certhigh.c
Normal file
1204
security/nss/lib/certhigh/certhigh.c
Normal file
File diff suppressed because it is too large
Load diff
31
security/nss/lib/certhigh/certhigh.gyp
Normal file
31
security/nss/lib/certhigh/certhigh.gyp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'certhi',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'certhigh.c',
|
||||
'certhtml.c',
|
||||
'certreq.c',
|
||||
'certvfy.c',
|
||||
'certvfypkix.c',
|
||||
'crlv2.c',
|
||||
'ocsp.c',
|
||||
'ocspsig.c',
|
||||
'xcrldist.c'
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports'
|
||||
]
|
||||
}
|
||||
],
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
||||
300
security/nss/lib/certhigh/certhtml.c
Normal file
300
security/nss/lib/certhigh/certhtml.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* certhtml.c --- convert a cert to html
|
||||
*/
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secitem.h"
|
||||
#include "sechash.h"
|
||||
#include "cert.h"
|
||||
#include "keyhi.h"
|
||||
#include "secder.h"
|
||||
#include "prprf.h"
|
||||
#include "secport.h"
|
||||
#include "secasn1.h"
|
||||
#include "pk11func.h"
|
||||
|
||||
static char *hex = "0123456789ABCDEF";
|
||||
|
||||
/*
|
||||
** Convert a der-encoded integer to a hex printable string form
|
||||
*/
|
||||
char *
|
||||
CERT_Hexify(SECItem *i, int do_colon)
|
||||
{
|
||||
unsigned char *cp, *end;
|
||||
char *rv, *o;
|
||||
|
||||
if (!i->len) {
|
||||
return PORT_Strdup("00");
|
||||
}
|
||||
|
||||
rv = o = (char *)PORT_Alloc(i->len * 3);
|
||||
if (!rv)
|
||||
return rv;
|
||||
|
||||
cp = i->data;
|
||||
end = cp + i->len;
|
||||
while (cp < end) {
|
||||
unsigned char ch = *cp++;
|
||||
*o++ = hex[(ch >> 4) & 0xf];
|
||||
*o++ = hex[ch & 0xf];
|
||||
if (cp != end) {
|
||||
if (do_colon) {
|
||||
*o++ = ':';
|
||||
}
|
||||
}
|
||||
}
|
||||
*o = 0; /* Null terminate the string */
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define BREAK "<br>"
|
||||
#define BREAKLEN 4
|
||||
#define COMMA ", "
|
||||
#define COMMALEN 2
|
||||
|
||||
#define MAX_OUS 20
|
||||
#define MAX_DC MAX_OUS
|
||||
|
||||
char *
|
||||
CERT_FormatName(CERTName *name)
|
||||
{
|
||||
CERTRDN **rdns;
|
||||
CERTRDN *rdn;
|
||||
CERTAVA **avas;
|
||||
CERTAVA *ava;
|
||||
char *buf = 0;
|
||||
char *tmpbuf = 0;
|
||||
SECItem *cn = 0;
|
||||
SECItem *email = 0;
|
||||
SECItem *org = 0;
|
||||
SECItem *loc = 0;
|
||||
SECItem *state = 0;
|
||||
SECItem *country = 0;
|
||||
SECItem *dq = 0;
|
||||
|
||||
unsigned len = 0;
|
||||
int tag;
|
||||
int i;
|
||||
int ou_count = 0;
|
||||
int dc_count = 0;
|
||||
PRBool first;
|
||||
SECItem *orgunit[MAX_OUS];
|
||||
SECItem *dc[MAX_DC];
|
||||
|
||||
/* Loop over name components and gather the interesting ones */
|
||||
rdns = name->rdns;
|
||||
while ((rdn = *rdns++) != 0) {
|
||||
avas = rdn->avas;
|
||||
while ((ava = *avas++) != 0) {
|
||||
tag = CERT_GetAVATag(ava);
|
||||
switch (tag) {
|
||||
case SEC_OID_AVA_COMMON_NAME:
|
||||
if (cn) {
|
||||
break;
|
||||
}
|
||||
cn = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!cn) {
|
||||
goto loser;
|
||||
}
|
||||
len += cn->len;
|
||||
break;
|
||||
case SEC_OID_AVA_COUNTRY_NAME:
|
||||
if (country) {
|
||||
break;
|
||||
}
|
||||
country = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!country) {
|
||||
goto loser;
|
||||
}
|
||||
len += country->len;
|
||||
break;
|
||||
case SEC_OID_AVA_LOCALITY:
|
||||
if (loc) {
|
||||
break;
|
||||
}
|
||||
loc = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!loc) {
|
||||
goto loser;
|
||||
}
|
||||
len += loc->len;
|
||||
break;
|
||||
case SEC_OID_AVA_STATE_OR_PROVINCE:
|
||||
if (state) {
|
||||
break;
|
||||
}
|
||||
state = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!state) {
|
||||
goto loser;
|
||||
}
|
||||
len += state->len;
|
||||
break;
|
||||
case SEC_OID_AVA_ORGANIZATION_NAME:
|
||||
if (org) {
|
||||
break;
|
||||
}
|
||||
org = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!org) {
|
||||
goto loser;
|
||||
}
|
||||
len += org->len;
|
||||
break;
|
||||
case SEC_OID_AVA_DN_QUALIFIER:
|
||||
if (dq) {
|
||||
break;
|
||||
}
|
||||
dq = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!dq) {
|
||||
goto loser;
|
||||
}
|
||||
len += dq->len;
|
||||
break;
|
||||
case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
|
||||
if (ou_count < MAX_OUS) {
|
||||
orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!orgunit[ou_count]) {
|
||||
goto loser;
|
||||
}
|
||||
len += orgunit[ou_count++]->len;
|
||||
}
|
||||
break;
|
||||
case SEC_OID_AVA_DC:
|
||||
if (dc_count < MAX_DC) {
|
||||
dc[dc_count] = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!dc[dc_count]) {
|
||||
goto loser;
|
||||
}
|
||||
len += dc[dc_count++]->len;
|
||||
}
|
||||
break;
|
||||
case SEC_OID_PKCS9_EMAIL_ADDRESS:
|
||||
case SEC_OID_RFC1274_MAIL:
|
||||
if (email) {
|
||||
break;
|
||||
}
|
||||
email = CERT_DecodeAVAValue(&ava->value);
|
||||
if (!email) {
|
||||
goto loser;
|
||||
}
|
||||
len += email->len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX - add some for formatting */
|
||||
len += 128;
|
||||
|
||||
/* allocate buffer */
|
||||
buf = (char *)PORT_Alloc(len);
|
||||
if (!buf) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
tmpbuf = buf;
|
||||
|
||||
if (cn) {
|
||||
PORT_Memcpy(tmpbuf, cn->data, cn->len);
|
||||
tmpbuf += cn->len;
|
||||
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
|
||||
tmpbuf += BREAKLEN;
|
||||
}
|
||||
if (email) {
|
||||
PORT_Memcpy(tmpbuf, email->data, email->len);
|
||||
tmpbuf += (email->len);
|
||||
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
|
||||
tmpbuf += BREAKLEN;
|
||||
}
|
||||
for (i = ou_count - 1; i >= 0; i--) {
|
||||
PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len);
|
||||
tmpbuf += (orgunit[i]->len);
|
||||
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
|
||||
tmpbuf += BREAKLEN;
|
||||
}
|
||||
if (dq) {
|
||||
PORT_Memcpy(tmpbuf, dq->data, dq->len);
|
||||
tmpbuf += (dq->len);
|
||||
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
|
||||
tmpbuf += BREAKLEN;
|
||||
}
|
||||
if (org) {
|
||||
PORT_Memcpy(tmpbuf, org->data, org->len);
|
||||
tmpbuf += (org->len);
|
||||
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
|
||||
tmpbuf += BREAKLEN;
|
||||
}
|
||||
for (i = dc_count - 1; i >= 0; i--) {
|
||||
PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len);
|
||||
tmpbuf += (dc[i]->len);
|
||||
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
|
||||
tmpbuf += BREAKLEN;
|
||||
}
|
||||
first = PR_TRUE;
|
||||
if (loc) {
|
||||
PORT_Memcpy(tmpbuf, loc->data, loc->len);
|
||||
tmpbuf += (loc->len);
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (state) {
|
||||
if (!first) {
|
||||
PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
|
||||
tmpbuf += COMMALEN;
|
||||
}
|
||||
PORT_Memcpy(tmpbuf, state->data, state->len);
|
||||
tmpbuf += (state->len);
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (country) {
|
||||
if (!first) {
|
||||
PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
|
||||
tmpbuf += COMMALEN;
|
||||
}
|
||||
PORT_Memcpy(tmpbuf, country->data, country->len);
|
||||
tmpbuf += (country->len);
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (!first) {
|
||||
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
|
||||
tmpbuf += BREAKLEN;
|
||||
}
|
||||
|
||||
*tmpbuf = 0;
|
||||
|
||||
/* fall through and clean */
|
||||
loser:
|
||||
if (cn) {
|
||||
SECITEM_FreeItem(cn, PR_TRUE);
|
||||
}
|
||||
if (email) {
|
||||
SECITEM_FreeItem(email, PR_TRUE);
|
||||
}
|
||||
for (i = ou_count - 1; i >= 0; i--) {
|
||||
SECITEM_FreeItem(orgunit[i], PR_TRUE);
|
||||
}
|
||||
if (dq) {
|
||||
SECITEM_FreeItem(dq, PR_TRUE);
|
||||
}
|
||||
if (org) {
|
||||
SECITEM_FreeItem(org, PR_TRUE);
|
||||
}
|
||||
for (i = dc_count - 1; i >= 0; i--) {
|
||||
SECITEM_FreeItem(dc[i], PR_TRUE);
|
||||
}
|
||||
if (loc) {
|
||||
SECITEM_FreeItem(loc, PR_TRUE);
|
||||
}
|
||||
if (state) {
|
||||
SECITEM_FreeItem(state, PR_TRUE);
|
||||
}
|
||||
if (country) {
|
||||
SECITEM_FreeItem(country, PR_TRUE);
|
||||
}
|
||||
|
||||
return (buf);
|
||||
}
|
||||
331
security/nss/lib/certhigh/certreq.c
Normal file
331
security/nss/lib/certhigh/certreq.c
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "cert.h"
|
||||
#include "certt.h"
|
||||
#include "secder.h"
|
||||
#include "key.h"
|
||||
#include "secitem.h"
|
||||
#include "secasn1.h"
|
||||
#include "secerr.h"
|
||||
|
||||
SEC_ASN1_MKSUB(SEC_AnyTemplate)
|
||||
|
||||
const SEC_ASN1Template CERT_AttributeTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(CERTAttribute) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(CERTAttribute, attrType) },
|
||||
{ SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(CERTAttribute, attrValue),
|
||||
SEC_ASN1_SUB(SEC_AnyTemplate) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_SetOfAttributeTemplate[] = {
|
||||
{ SEC_ASN1_SET_OF, 0, CERT_AttributeTemplate },
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_CertificateRequestTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(CERTCertificateRequest) },
|
||||
{ SEC_ASN1_INTEGER,
|
||||
offsetof(CERTCertificateRequest, version) },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(CERTCertificateRequest, subject),
|
||||
CERT_NameTemplate },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(CERTCertificateRequest, subjectPublicKeyInfo),
|
||||
CERT_SubjectPublicKeyInfoTemplate },
|
||||
{ SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(CERTCertificateRequest, attributes),
|
||||
CERT_SetOfAttributeTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateRequestTemplate)
|
||||
|
||||
CERTCertificate *
|
||||
CERT_CreateCertificate(unsigned long serialNumber,
|
||||
CERTName *issuer,
|
||||
CERTValidity *validity,
|
||||
CERTCertificateRequest *req)
|
||||
{
|
||||
CERTCertificate *c;
|
||||
int rv;
|
||||
PLArenaPool *arena;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
|
||||
if (!arena) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
c = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));
|
||||
|
||||
if (!c) {
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->referenceCount = 1;
|
||||
c->arena = arena;
|
||||
|
||||
/*
|
||||
* Default is a plain version 1.
|
||||
* If extensions are added, it will get changed as appropriate.
|
||||
*/
|
||||
rv = DER_SetUInteger(arena, &c->version, SEC_CERTIFICATE_VERSION_1);
|
||||
if (rv)
|
||||
goto loser;
|
||||
|
||||
rv = DER_SetUInteger(arena, &c->serialNumber, serialNumber);
|
||||
if (rv)
|
||||
goto loser;
|
||||
|
||||
rv = CERT_CopyName(arena, &c->issuer, issuer);
|
||||
if (rv)
|
||||
goto loser;
|
||||
|
||||
rv = CERT_CopyValidity(arena, &c->validity, validity);
|
||||
if (rv)
|
||||
goto loser;
|
||||
|
||||
rv = CERT_CopyName(arena, &c->subject, &req->subject);
|
||||
if (rv)
|
||||
goto loser;
|
||||
rv = SECKEY_CopySubjectPublicKeyInfo(arena, &c->subjectPublicKeyInfo,
|
||||
&req->subjectPublicKeyInfo);
|
||||
if (rv)
|
||||
goto loser;
|
||||
|
||||
return c;
|
||||
|
||||
loser:
|
||||
CERT_DestroyCertificate(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* It's clear from the comments that the original author of this
|
||||
* function expected the template for certificate requests to treat
|
||||
* the attributes as a SET OF ANY. This function expected to be
|
||||
* passed an array of SECItems each of which contained an already encoded
|
||||
* Attribute. But the cert request template does not treat the
|
||||
* Attributes as a SET OF ANY, and AFAIK never has. Instead the template
|
||||
* encodes attributes as a SET OF xxxxxxx. That is, it expects to encode
|
||||
* each of the Attributes, not have them pre-encoded. Consequently an
|
||||
* array of SECItems containing encoded Attributes is of no value to this
|
||||
* function. But we cannot change the signature of this public function.
|
||||
* It must continue to take SECItems.
|
||||
*
|
||||
* I have recoded this function so that each SECItem contains an
|
||||
* encoded cert extension. The encoded cert extensions form the list for the
|
||||
* single attribute of the cert request. In this implementation there is at most
|
||||
* one attribute and it is always of type SEC_OID_PKCS9_EXTENSION_REQUEST.
|
||||
*/
|
||||
|
||||
CERTCertificateRequest *
|
||||
CERT_CreateCertificateRequest(CERTName *subject,
|
||||
CERTSubjectPublicKeyInfo *spki,
|
||||
SECItem **attributes)
|
||||
{
|
||||
CERTCertificateRequest *certreq;
|
||||
PLArenaPool *arena;
|
||||
CERTAttribute *attribute;
|
||||
SECOidData *oidData;
|
||||
SECStatus rv;
|
||||
int i = 0;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
certreq = PORT_ArenaZNew(arena, CERTCertificateRequest);
|
||||
if (!certreq) {
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
/* below here it is safe to goto loser */
|
||||
|
||||
certreq->arena = arena;
|
||||
|
||||
rv = DER_SetUInteger(arena, &certreq->version,
|
||||
SEC_CERTIFICATE_REQUEST_VERSION);
|
||||
if (rv != SECSuccess)
|
||||
goto loser;
|
||||
|
||||
rv = CERT_CopyName(arena, &certreq->subject, subject);
|
||||
if (rv != SECSuccess)
|
||||
goto loser;
|
||||
|
||||
rv = SECKEY_CopySubjectPublicKeyInfo(arena,
|
||||
&certreq->subjectPublicKeyInfo,
|
||||
spki);
|
||||
if (rv != SECSuccess)
|
||||
goto loser;
|
||||
|
||||
certreq->attributes = PORT_ArenaZNewArray(arena, CERTAttribute *, 2);
|
||||
if (!certreq->attributes)
|
||||
goto loser;
|
||||
|
||||
/* Copy over attribute information */
|
||||
if (!attributes || !attributes[0]) {
|
||||
/*
|
||||
** Invent empty attribute information. According to the
|
||||
** pkcs#10 spec, attributes has this ASN.1 type:
|
||||
**
|
||||
** attributes [0] IMPLICIT Attributes
|
||||
**
|
||||
** Which means, we should create a NULL terminated list
|
||||
** with the first entry being NULL;
|
||||
*/
|
||||
certreq->attributes[0] = NULL;
|
||||
return certreq;
|
||||
}
|
||||
|
||||
/* allocate space for attributes */
|
||||
attribute = PORT_ArenaZNew(arena, CERTAttribute);
|
||||
if (!attribute)
|
||||
goto loser;
|
||||
|
||||
oidData = SECOID_FindOIDByTag(SEC_OID_PKCS9_EXTENSION_REQUEST);
|
||||
PORT_Assert(oidData);
|
||||
if (!oidData)
|
||||
goto loser;
|
||||
rv = SECITEM_CopyItem(arena, &attribute->attrType, &oidData->oid);
|
||||
if (rv != SECSuccess)
|
||||
goto loser;
|
||||
|
||||
for (i = 0; attributes[i] != NULL; i++)
|
||||
;
|
||||
attribute->attrValue = PORT_ArenaZNewArray(arena, SECItem *, i + 1);
|
||||
if (!attribute->attrValue)
|
||||
goto loser;
|
||||
|
||||
/* copy attributes */
|
||||
for (i = 0; attributes[i]; i++) {
|
||||
/*
|
||||
** Attributes are a SetOf Attribute which implies
|
||||
** lexigraphical ordering. It is assumes that the
|
||||
** attributes are passed in sorted. If we need to
|
||||
** add functionality to sort them, there is an
|
||||
** example in the PKCS 7 code.
|
||||
*/
|
||||
attribute->attrValue[i] = SECITEM_ArenaDupItem(arena, attributes[i]);
|
||||
if (!attribute->attrValue[i])
|
||||
goto loser;
|
||||
}
|
||||
|
||||
certreq->attributes[0] = attribute;
|
||||
|
||||
return certreq;
|
||||
|
||||
loser:
|
||||
CERT_DestroyCertificateRequest(certreq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CERT_DestroyCertificateRequest(CERTCertificateRequest *req)
|
||||
{
|
||||
if (req && req->arena) {
|
||||
PORT_FreeArena(req->arena, PR_FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
setCRExt(void *o, CERTCertExtension **exts)
|
||||
{
|
||||
((CERTCertificateRequest *)o)->attributes = (struct CERTAttributeStr **)exts;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set up to start gathering cert extensions for a cert request.
|
||||
** The list is created as CertExtensions and converted to an
|
||||
** attribute list by CERT_FinishCRAttributes().
|
||||
*/
|
||||
extern void *cert_StartExtensions(void *owner, PLArenaPool *ownerArena,
|
||||
void (*setExts)(void *object, CERTCertExtension **exts));
|
||||
void *
|
||||
CERT_StartCertificateRequestAttributes(CERTCertificateRequest *req)
|
||||
{
|
||||
return (cert_StartExtensions((void *)req, req->arena, setCRExt));
|
||||
}
|
||||
|
||||
/*
|
||||
** At entry req->attributes actually contains an list of cert extensions--
|
||||
** req-attributes is overloaded until the list is DER encoded (the first
|
||||
** ...EncodeItem() below).
|
||||
** We turn this into an attribute list by encapsulating it
|
||||
** in a PKCS 10 Attribute structure
|
||||
*/
|
||||
SECStatus
|
||||
CERT_FinishCertificateRequestAttributes(CERTCertificateRequest *req)
|
||||
{
|
||||
SECItem *extlist;
|
||||
SECOidData *oidrec;
|
||||
CERTAttribute *attribute;
|
||||
|
||||
if (!req || !req->arena) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (req->attributes == NULL || req->attributes[0] == NULL)
|
||||
return SECSuccess;
|
||||
|
||||
extlist = SEC_ASN1EncodeItem(req->arena, NULL, &req->attributes,
|
||||
SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate));
|
||||
if (extlist == NULL)
|
||||
return (SECFailure);
|
||||
|
||||
oidrec = SECOID_FindOIDByTag(SEC_OID_PKCS9_EXTENSION_REQUEST);
|
||||
if (oidrec == NULL)
|
||||
return SECFailure;
|
||||
|
||||
/* now change the list of cert extensions into a list of attributes
|
||||
*/
|
||||
req->attributes = PORT_ArenaZNewArray(req->arena, CERTAttribute *, 2);
|
||||
|
||||
attribute = PORT_ArenaZNew(req->arena, CERTAttribute);
|
||||
|
||||
if (req->attributes == NULL || attribute == NULL ||
|
||||
SECITEM_CopyItem(req->arena, &attribute->attrType, &oidrec->oid) != 0) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
attribute->attrValue = PORT_ArenaZNewArray(req->arena, SECItem *, 2);
|
||||
|
||||
if (attribute->attrValue == NULL)
|
||||
return SECFailure;
|
||||
|
||||
attribute->attrValue[0] = extlist;
|
||||
attribute->attrValue[1] = NULL;
|
||||
req->attributes[0] = attribute;
|
||||
req->attributes[1] = NULL;
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_GetCertificateRequestExtensions(CERTCertificateRequest *req,
|
||||
CERTCertExtension ***exts)
|
||||
{
|
||||
if (req == NULL || exts == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (req->attributes == NULL || *req->attributes == NULL)
|
||||
return SECSuccess;
|
||||
|
||||
if ((*req->attributes)->attrValue == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
return (SEC_ASN1DecodeItem(req->arena, exts,
|
||||
SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate),
|
||||
(*req->attributes)->attrValue[0]));
|
||||
}
|
||||
2082
security/nss/lib/certhigh/certvfy.c
Normal file
2082
security/nss/lib/certhigh/certvfy.c
Normal file
File diff suppressed because it is too large
Load diff
2305
security/nss/lib/certhigh/certvfypkix.c
Normal file
2305
security/nss/lib/certhigh/certvfypkix.c
Normal file
File diff suppressed because it is too large
Load diff
15
security/nss/lib/certhigh/config.mk
Normal file
15
security/nss/lib/certhigh/config.mk
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#
|
||||
# Override TARGETS variable so that only static libraries
|
||||
# are specifed as dependencies within rules.mk.
|
||||
#
|
||||
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
160
security/nss/lib/certhigh/crlv2.c
Normal file
160
security/nss/lib/certhigh/crlv2.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Code for dealing with x.509 v3 crl and crl entries extensions.
|
||||
*/
|
||||
|
||||
#include "cert.h"
|
||||
#include "secitem.h"
|
||||
#include "secoid.h"
|
||||
#include "secoidt.h"
|
||||
#include "secder.h"
|
||||
#include "secasn1.h"
|
||||
#include "certxutl.h"
|
||||
|
||||
SECStatus
|
||||
CERT_FindCRLExtensionByOID(CERTCrl *crl, SECItem *oid, SECItem *value)
|
||||
{
|
||||
return (cert_FindExtensionByOID(crl->extensions, oid, value));
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FindCRLExtension(CERTCrl *crl, int tag, SECItem *value)
|
||||
{
|
||||
return (cert_FindExtension(crl->extensions, tag, value));
|
||||
}
|
||||
|
||||
/* Callback to set extensions and adjust verison */
|
||||
static void
|
||||
SetCrlExts(void *object, CERTCertExtension **exts)
|
||||
{
|
||||
CERTCrl *crl = (CERTCrl *)object;
|
||||
|
||||
crl->extensions = exts;
|
||||
DER_SetUInteger(crl->arena, &crl->version, SEC_CRL_VERSION_2);
|
||||
}
|
||||
|
||||
void *
|
||||
CERT_StartCRLExtensions(CERTCrl *crl)
|
||||
{
|
||||
return (cert_StartExtensions((void *)crl, crl->arena, SetCrlExts));
|
||||
}
|
||||
|
||||
static void
|
||||
SetCrlEntryExts(void *object, CERTCertExtension **exts)
|
||||
{
|
||||
CERTCrlEntry *crlEntry = (CERTCrlEntry *)object;
|
||||
|
||||
crlEntry->extensions = exts;
|
||||
}
|
||||
|
||||
void *
|
||||
CERT_StartCRLEntryExtensions(CERTCrl *crl, CERTCrlEntry *entry)
|
||||
{
|
||||
return (cert_StartExtensions(entry, crl->arena, SetCrlEntryExts));
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FindCRLNumberExten(PLArenaPool *arena, CERTCrl *crl,
|
||||
SECItem *value)
|
||||
{
|
||||
SECItem encodedExtenValue;
|
||||
SECItem *tmpItem = NULL;
|
||||
SECStatus rv;
|
||||
void *mark = NULL;
|
||||
|
||||
encodedExtenValue.data = NULL;
|
||||
encodedExtenValue.len = 0;
|
||||
|
||||
rv = cert_FindExtension(crl->extensions, SEC_OID_X509_CRL_NUMBER,
|
||||
&encodedExtenValue);
|
||||
if (rv != SECSuccess)
|
||||
return (rv);
|
||||
|
||||
mark = PORT_ArenaMark(arena);
|
||||
|
||||
tmpItem = SECITEM_ArenaDupItem(arena, &encodedExtenValue);
|
||||
if (tmpItem) {
|
||||
rv = SEC_QuickDERDecodeItem(arena, value,
|
||||
SEC_ASN1_GET(SEC_IntegerTemplate),
|
||||
tmpItem);
|
||||
} else {
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
PORT_Free(encodedExtenValue.data);
|
||||
if (rv == SECFailure) {
|
||||
PORT_ArenaRelease(arena, mark);
|
||||
} else {
|
||||
PORT_ArenaUnmark(arena, mark);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FindCRLEntryReasonExten(CERTCrlEntry *crlEntry,
|
||||
CERTCRLEntryReasonCode *value)
|
||||
{
|
||||
SECItem wrapperItem = { siBuffer, 0 };
|
||||
SECItem tmpItem = { siBuffer, 0 };
|
||||
SECStatus rv;
|
||||
PLArenaPool *arena = NULL;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
rv = cert_FindExtension(crlEntry->extensions, SEC_OID_X509_REASON_CODE,
|
||||
&wrapperItem);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = SEC_QuickDERDecodeItem(arena, &tmpItem,
|
||||
SEC_ASN1_GET(SEC_EnumeratedTemplate),
|
||||
&wrapperItem);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
*value = (CERTCRLEntryReasonCode)DER_GetInteger(&tmpItem);
|
||||
|
||||
loser:
|
||||
if (arena) {
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
}
|
||||
|
||||
if (wrapperItem.data) {
|
||||
PORT_Free(wrapperItem.data);
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FindInvalidDateExten(CERTCrl *crl, PRTime *value)
|
||||
{
|
||||
SECItem encodedExtenValue;
|
||||
SECItem decodedExtenValue = { siBuffer, 0 };
|
||||
SECStatus rv;
|
||||
|
||||
encodedExtenValue.data = decodedExtenValue.data = NULL;
|
||||
encodedExtenValue.len = decodedExtenValue.len = 0;
|
||||
|
||||
rv = cert_FindExtension(crl->extensions, SEC_OID_X509_INVALID_DATE, &encodedExtenValue);
|
||||
if (rv != SECSuccess)
|
||||
return (rv);
|
||||
|
||||
rv = SEC_ASN1DecodeItem(NULL, &decodedExtenValue,
|
||||
SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
|
||||
&encodedExtenValue);
|
||||
if (rv == SECSuccess)
|
||||
rv = DER_GeneralizedTimeToTime(value, &encodedExtenValue);
|
||||
PORT_Free(decodedExtenValue.data);
|
||||
PORT_Free(encodedExtenValue.data);
|
||||
return (rv);
|
||||
}
|
||||
33
security/nss/lib/certhigh/exports.gyp
Normal file
33
security/nss/lib/certhigh/exports.gyp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'lib_certhigh_exports',
|
||||
'type': 'none',
|
||||
'copies': [
|
||||
{
|
||||
'files': [
|
||||
'ocsp.h',
|
||||
'ocspt.h'
|
||||
],
|
||||
'destination': '<(nss_public_dist_dir)/<(module)'
|
||||
},
|
||||
{
|
||||
'files': [
|
||||
'ocspi.h',
|
||||
'ocspti.h'
|
||||
],
|
||||
'destination': '<(nss_private_dist_dir)/<(module)'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
||||
34
security/nss/lib/certhigh/manifest.mn
Normal file
34
security/nss/lib/certhigh/manifest.mn
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
CORE_DEPTH = ../..
|
||||
|
||||
EXPORTS = \
|
||||
ocsp.h \
|
||||
ocspt.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
ocspti.h \
|
||||
ocspi.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE = nss
|
||||
|
||||
CSRCS = \
|
||||
certhtml.c \
|
||||
certreq.c \
|
||||
crlv2.c \
|
||||
ocsp.c \
|
||||
ocspsig.c \
|
||||
certhigh.c \
|
||||
certvfy.c \
|
||||
certvfypkix.c \
|
||||
xcrldist.c \
|
||||
$(NULL)
|
||||
|
||||
LIBRARY_NAME = certhi
|
||||
|
||||
# This part of the code, including all sub-dirs, can be optimized for size
|
||||
export ALLOW_OPT_CODE_SIZE = 1
|
||||
6120
security/nss/lib/certhigh/ocsp.c
Normal file
6120
security/nss/lib/certhigh/ocsp.c
Normal file
File diff suppressed because it is too large
Load diff
723
security/nss/lib/certhigh/ocsp.h
Normal file
723
security/nss/lib/certhigh/ocsp.h
Normal file
|
|
@ -0,0 +1,723 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Interface to the OCSP implementation.
|
||||
*/
|
||||
|
||||
#ifndef _OCSP_H_
|
||||
#define _OCSP_H_
|
||||
|
||||
#include "plarena.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "keyt.h"
|
||||
#include "certt.h"
|
||||
#include "ocspt.h"
|
||||
|
||||
/************************************************************************/
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
* This function registers the HttpClient with whose functions the
|
||||
* HttpClientFcn structure has been populated as the default Http
|
||||
* client.
|
||||
*
|
||||
* The function table must be a global object.
|
||||
* The caller must ensure that NSS will be able to call
|
||||
* the registered functions for the lifetime of the process.
|
||||
*/
|
||||
extern SECStatus
|
||||
SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable);
|
||||
|
||||
/*
|
||||
* This function obtains the HttpClient which has been registered
|
||||
* by an earlier call to SEC_RegisterDefaultHttpClient.
|
||||
*/
|
||||
extern const SEC_HttpClientFcn *
|
||||
SEC_GetRegisteredHttpClient(void);
|
||||
|
||||
/*
|
||||
* Sets parameters that control NSS' internal OCSP cache.
|
||||
* maxCacheEntries, special varlues are:
|
||||
* -1 disable cache
|
||||
* 0 unlimited cache entries
|
||||
* minimumSecondsToNextFetchAttempt:
|
||||
* whenever an OCSP request was attempted or completed over the network,
|
||||
* wait at least this number of seconds before trying to fetch again.
|
||||
* maximumSecondsToNextFetchAttempt:
|
||||
* this is the maximum age of a cached response we allow, until we try
|
||||
* to fetch an updated response, even if the OCSP responder expects
|
||||
* that newer information update will not be available yet.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_OCSPCacheSettings(PRInt32 maxCacheEntries,
|
||||
PRUint32 minimumSecondsToNextFetchAttempt,
|
||||
PRUint32 maximumSecondsToNextFetchAttempt);
|
||||
|
||||
/*
|
||||
* Set the desired behaviour on OCSP failures.
|
||||
* See definition of ocspFailureMode for allowed choices.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode);
|
||||
|
||||
/*
|
||||
* Configure the maximum time NSS will wait for an OCSP response.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_SetOCSPTimeout(PRUint32 seconds);
|
||||
|
||||
/*
|
||||
* Removes all items currently stored in the OCSP cache.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_ClearOCSPCache(void);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_EnableOCSPChecking
|
||||
* Turns on OCSP checking for the given certificate database.
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* Certificate database for which OCSP checking will be enabled.
|
||||
* RETURN:
|
||||
* Returns SECFailure if an error occurred (likely only problem
|
||||
* allocating memory); SECSuccess otherwise.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_EnableOCSPChecking(CERTCertDBHandle *handle);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_DisableOCSPChecking
|
||||
* Turns off OCSP checking for the given certificate database.
|
||||
* This routine disables OCSP checking. Though it will return
|
||||
* SECFailure if OCSP checking is not enabled, it is "safe" to
|
||||
* call it that way and just ignore the return value, if it is
|
||||
* easier to just call it than to "remember" whether it is enabled.
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* Certificate database for which OCSP checking will be disabled.
|
||||
* RETURN:
|
||||
* Returns SECFailure if an error occurred (usually means that OCSP
|
||||
* checking was not enabled or status contexts were not initialized --
|
||||
* error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_DisableOCSPChecking(CERTCertDBHandle *handle);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_SetOCSPDefaultResponder
|
||||
* Specify the location and cert of the default responder.
|
||||
* If OCSP checking is already enabled *and* use of a default responder
|
||||
* is also already enabled, all OCSP checking from now on will go directly
|
||||
* to the specified responder. If OCSP checking is not enabled, or if
|
||||
* it is but use of a default responder is not enabled, the information
|
||||
* will be recorded and take effect whenever both are enabled.
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* Cert database on which OCSP checking should use the default responder.
|
||||
* const char *url
|
||||
* The location of the default responder (e.g. "http://foo.com:80/ocsp")
|
||||
* Note that the location will not be tested until the first attempt
|
||||
* to send a request there.
|
||||
* const char *name
|
||||
* The nickname of the cert to trust (expected) to sign the OCSP responses.
|
||||
* If the corresponding cert cannot be found, SECFailure is returned.
|
||||
* RETURN:
|
||||
* Returns SECFailure if an error occurred; SECSuccess otherwise.
|
||||
* The most likely error is that the cert for "name" could not be found
|
||||
* (probably SEC_ERROR_UNKNOWN_CERT). Other errors are low-level (no memory,
|
||||
* bad database, etc.).
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle,
|
||||
const char *url, const char *name);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_EnableOCSPDefaultResponder
|
||||
* Turns on use of a default responder when OCSP checking.
|
||||
* If OCSP checking is already enabled, this will make subsequent checks
|
||||
* go directly to the default responder. (The location of the responder
|
||||
* and the nickname of the responder cert must already be specified.)
|
||||
* If OCSP checking is not enabled, this will be recorded and take effect
|
||||
* whenever it is enabled.
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* Cert database on which OCSP checking should use the default responder.
|
||||
* RETURN:
|
||||
* Returns SECFailure if an error occurred; SECSuccess otherwise.
|
||||
* No errors are especially likely unless the caller did not previously
|
||||
* perform a successful call to SetOCSPDefaultResponder (in which case
|
||||
* the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER).
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_DisableOCSPDefaultResponder
|
||||
* Turns off use of a default responder when OCSP checking.
|
||||
* (Does nothing if use of a default responder is not enabled.)
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* Cert database on which OCSP checking should stop using a default
|
||||
* responder.
|
||||
* RETURN:
|
||||
* Returns SECFailure if an error occurred; SECSuccess otherwise.
|
||||
* Errors very unlikely (like random memory corruption...).
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle);
|
||||
|
||||
/* If forcePost is set, OCSP requests will only be sent using the HTTP POST
|
||||
* method. When forcePost is not set, OCSP requests will be sent using the
|
||||
* HTTP GET method, with a fallback to POST when we fail to receive a response
|
||||
* and/or when we receive an uncacheable response like "Unknown."
|
||||
*
|
||||
* The default is to use GET and fallback to POST.
|
||||
*/
|
||||
extern SECStatus CERT_ForcePostMethodForOCSP(PRBool forcePost);
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------
|
||||
* The Functions above are those expected to be used by a client
|
||||
* providing OCSP status checking along with every cert verification.
|
||||
* The functions below are for OCSP testing, debugging, or clients
|
||||
* or servers performing more specialized OCSP tasks.
|
||||
* -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_CreateOCSPRequest
|
||||
* Creates a CERTOCSPRequest, requesting the status of the certs in
|
||||
* the given list.
|
||||
* INPUTS:
|
||||
* CERTCertList *certList
|
||||
* A list of certs for which status will be requested.
|
||||
* Note that all of these certificates should have the same issuer,
|
||||
* or it's expected the response will be signed by a trusted responder.
|
||||
* If the certs need to be broken up into multiple requests, that
|
||||
* must be handled by the caller (and thus by having multiple calls
|
||||
* to this routine), who knows about where the request(s) are being
|
||||
* sent and whether there are any trusted responders in place.
|
||||
* PRTime time
|
||||
* Indicates the time for which the certificate status is to be
|
||||
* determined -- this may be used in the search for the cert's issuer
|
||||
* but has no effect on the request itself.
|
||||
* PRBool addServiceLocator
|
||||
* If true, the Service Locator extension should be added to the
|
||||
* single request(s) for each cert.
|
||||
* CERTCertificate *signerCert
|
||||
* If non-NULL, means sign the request using this cert. Otherwise,
|
||||
* do not sign.
|
||||
* XXX note that request signing is not yet supported; see comment in code
|
||||
* RETURN:
|
||||
* A pointer to a CERTOCSPRequest structure containing an OCSP request
|
||||
* for the cert list. On error, null is returned, with an error set
|
||||
* indicating the reason. This is likely SEC_ERROR_UNKNOWN_ISSUER.
|
||||
* (The issuer is needed to create a request for the certificate.)
|
||||
* Other errors are low-level problems (no memory, bad database, etc.).
|
||||
*/
|
||||
extern CERTOCSPRequest *
|
||||
CERT_CreateOCSPRequest(CERTCertList *certList, PRTime time,
|
||||
PRBool addServiceLocator,
|
||||
CERTCertificate *signerCert);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_AddOCSPAcceptableResponses
|
||||
* Add the AcceptableResponses extension to an OCSP Request.
|
||||
* INPUTS:
|
||||
* CERTOCSPRequest *request
|
||||
* The request to which the extension should be added.
|
||||
* SECOidTag responseType0, ...
|
||||
* A list (of one or more) of SECOidTag -- each of the response types
|
||||
* to be added. The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE.
|
||||
* (This marks the end of the list, and it must be specified because a
|
||||
* client conforming to the OCSP standard is required to handle the basic
|
||||
* response type.) The OIDs are not checked in any way.
|
||||
* RETURN:
|
||||
* SECSuccess if the extension is added; SECFailure if anything goes wrong.
|
||||
* All errors are internal or low-level problems (e.g. no memory).
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request,
|
||||
SECOidTag responseType0, ...);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_EncodeOCSPRequest
|
||||
* DER encodes an OCSP Request, possibly adding a signature as well.
|
||||
* XXX Signing is not yet supported, however; see comments in code.
|
||||
* INPUTS:
|
||||
* PLArenaPool *arena
|
||||
* The return value is allocated from here.
|
||||
* If a NULL is passed in, allocation is done from the heap instead.
|
||||
* CERTOCSPRequest *request
|
||||
* The request to be encoded.
|
||||
* void *pwArg
|
||||
* Pointer to argument for password prompting, if needed. (Definitely
|
||||
* not needed if not signing.)
|
||||
* RETURN:
|
||||
* Returns a NULL on error and a pointer to the SECItem with the
|
||||
* encoded value otherwise. Any error is likely to be low-level
|
||||
* (e.g. no memory).
|
||||
*/
|
||||
extern SECItem *
|
||||
CERT_EncodeOCSPRequest(PLArenaPool *arena, CERTOCSPRequest *request,
|
||||
void *pwArg);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_DecodeOCSPRequest
|
||||
* Decode a DER encoded OCSP Request.
|
||||
* INPUTS:
|
||||
* SECItem *src
|
||||
* Pointer to a SECItem holding DER encoded OCSP Request.
|
||||
* RETURN:
|
||||
* Returns a pointer to a CERTOCSPRequest containing the decoded request.
|
||||
* On error, returns NULL. Most likely error is trouble decoding
|
||||
* (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory).
|
||||
*/
|
||||
extern CERTOCSPRequest *
|
||||
CERT_DecodeOCSPRequest(const SECItem *src);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_DestroyOCSPRequest
|
||||
* Frees an OCSP Request structure.
|
||||
* INPUTS:
|
||||
* CERTOCSPRequest *request
|
||||
* Pointer to CERTOCSPRequest to be freed.
|
||||
* RETURN:
|
||||
* No return value; no errors.
|
||||
*/
|
||||
extern void
|
||||
CERT_DestroyOCSPRequest(CERTOCSPRequest *request);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_DecodeOCSPResponse
|
||||
* Decode a DER encoded OCSP Response.
|
||||
* INPUTS:
|
||||
* SECItem *src
|
||||
* Pointer to a SECItem holding DER encoded OCSP Response.
|
||||
* RETURN:
|
||||
* Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response);
|
||||
* the caller is responsible for destroying it. Or NULL if error (either
|
||||
* response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE),
|
||||
* it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE),
|
||||
* or a low-level or internal error occurred).
|
||||
*/
|
||||
extern CERTOCSPResponse *
|
||||
CERT_DecodeOCSPResponse(const SECItem *src);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_DestroyOCSPResponse
|
||||
* Frees an OCSP Response structure.
|
||||
* INPUTS:
|
||||
* CERTOCSPResponse *request
|
||||
* Pointer to CERTOCSPResponse to be freed.
|
||||
* RETURN:
|
||||
* No return value; no errors.
|
||||
*/
|
||||
extern void
|
||||
CERT_DestroyOCSPResponse(CERTOCSPResponse *response);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_GetEncodedOCSPResponse
|
||||
* Creates and sends a request to an OCSP responder, then reads and
|
||||
* returns the (encoded) response.
|
||||
* INPUTS:
|
||||
* PLArenaPool *arena
|
||||
* Pointer to arena from which return value will be allocated.
|
||||
* If NULL, result will be allocated from the heap (and thus should
|
||||
* be freed via SECITEM_FreeItem).
|
||||
* CERTCertList *certList
|
||||
* A list of certs for which status will be requested.
|
||||
* Note that all of these certificates should have the same issuer,
|
||||
* or it's expected the response will be signed by a trusted responder.
|
||||
* If the certs need to be broken up into multiple requests, that
|
||||
* must be handled by the caller (and thus by having multiple calls
|
||||
* to this routine), who knows about where the request(s) are being
|
||||
* sent and whether there are any trusted responders in place.
|
||||
* const char *location
|
||||
* The location of the OCSP responder (a URL).
|
||||
* PRTime time
|
||||
* Indicates the time for which the certificate status is to be
|
||||
* determined -- this may be used in the search for the cert's issuer
|
||||
* but has no other bearing on the operation.
|
||||
* PRBool addServiceLocator
|
||||
* If true, the Service Locator extension should be added to the
|
||||
* single request(s) for each cert.
|
||||
* CERTCertificate *signerCert
|
||||
* If non-NULL, means sign the request using this cert. Otherwise,
|
||||
* do not sign.
|
||||
* void *pwArg
|
||||
* Pointer to argument for password prompting, if needed. (Definitely
|
||||
* not needed if not signing.)
|
||||
* OUTPUTS:
|
||||
* CERTOCSPRequest **pRequest
|
||||
* Pointer in which to store the OCSP request created for the given
|
||||
* list of certificates. It is only filled in if the entire operation
|
||||
* is successful and the pointer is not null -- and in that case the
|
||||
* caller is then reponsible for destroying it.
|
||||
* RETURN:
|
||||
* Returns a pointer to the SECItem holding the response.
|
||||
* On error, returns null with error set describing the reason:
|
||||
* SEC_ERROR_UNKNOWN_ISSUER
|
||||
* SEC_ERROR_CERT_BAD_ACCESS_LOCATION
|
||||
* SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
|
||||
* Other errors are low-level problems (no memory, bad database, etc.).
|
||||
*/
|
||||
extern SECItem *
|
||||
CERT_GetEncodedOCSPResponse(PLArenaPool *arena, CERTCertList *certList,
|
||||
const char *location, PRTime time,
|
||||
PRBool addServiceLocator,
|
||||
CERTCertificate *signerCert, void *pwArg,
|
||||
CERTOCSPRequest **pRequest);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_VerifyOCSPResponseSignature
|
||||
* Check the signature on an OCSP Response. Will also perform a
|
||||
* verification of the signer's certificate. Note, however, that a
|
||||
* successful verification does not make any statement about the
|
||||
* signer's *authority* to provide status for the certificate(s),
|
||||
* that must be checked individually for each certificate.
|
||||
* INPUTS:
|
||||
* CERTOCSPResponse *response
|
||||
* Pointer to response structure with signature to be checked.
|
||||
* CERTCertDBHandle *handle
|
||||
* Pointer to CERTCertDBHandle for certificate DB to use for verification.
|
||||
* void *pwArg
|
||||
* Pointer to argument for password prompting, if needed.
|
||||
* CERTCertificate *issuerCert
|
||||
* Issuer of the certificate that generated the OCSP request.
|
||||
* OUTPUTS:
|
||||
* CERTCertificate **pSignerCert
|
||||
* Pointer in which to store signer's certificate; only filled-in if
|
||||
* non-null.
|
||||
* RETURN:
|
||||
* Returns SECSuccess when signature is valid, anything else means invalid.
|
||||
* Possible errors set:
|
||||
* SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID
|
||||
* SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time
|
||||
* SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
|
||||
* SEC_ERROR_BAD_SIGNATURE - the signature did not verify
|
||||
* Other errors are any of the many possible failures in cert verification
|
||||
* (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
|
||||
* verifying the signer's cert, or low-level problems (no memory, etc.)
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,
|
||||
CERTCertDBHandle *handle, void *pwArg,
|
||||
CERTCertificate **pSignerCert,
|
||||
CERTCertificate *issuerCert);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation
|
||||
* Get the value of the URI of the OCSP responder for the given cert.
|
||||
* This is found in the (optional) Authority Information Access extension
|
||||
* in the cert.
|
||||
* INPUTS:
|
||||
* CERTCertificate *cert
|
||||
* The certificate being examined.
|
||||
* RETURN:
|
||||
* char *
|
||||
* A copy of the URI for the OCSP method, if found. If either the
|
||||
* extension is not present or it does not contain an entry for OCSP,
|
||||
* SEC_ERROR_EXTENSION_NOT_FOUND will be set and a NULL returned.
|
||||
* Any other error will also result in a NULL being returned.
|
||||
*
|
||||
* This result should be freed (via PORT_Free) when no longer in use.
|
||||
*/
|
||||
extern char *
|
||||
CERT_GetOCSPAuthorityInfoAccessLocation(const CERTCertificate *cert);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_RegisterAlternateOCSPAIAInfoCallBack
|
||||
* This function serves two purposes.
|
||||
* 1) It registers the address of a callback function that will be
|
||||
* called for certs that have no OCSP AIA extension, to see if the
|
||||
* callback wishes to supply an alternative URL for such an OCSP inquiry.
|
||||
* 2) It outputs the previously registered function's address to the
|
||||
* address supplied by the caller, unless that is NULL.
|
||||
* The registered callback function returns NULL, or an allocated string
|
||||
* that may be subsequently freed by calling PORT_Free().
|
||||
* RETURN:
|
||||
* SECSuccess or SECFailure (if the library is not yet intialized)
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_RegisterAlternateOCSPAIAInfoCallBack(
|
||||
CERT_StringFromCertFcn newCallback,
|
||||
CERT_StringFromCertFcn *oldCallback);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_ParseURL
|
||||
* Parse a URI into hostname, port, and path. The scheme in the URI must
|
||||
* be "http".
|
||||
* INPUTS:
|
||||
* const char *url
|
||||
* The URI to be parsed
|
||||
* OUTPUTS:
|
||||
* char **pHostname
|
||||
* Pointer to store the hostname obtained from the URI.
|
||||
* This result should be freed (via PORT_Free) when no longer in use.
|
||||
* PRUint16 *pPort
|
||||
* Pointer to store the port number obtained from the URI.
|
||||
* char **pPath
|
||||
* Pointer to store the path obtained from the URI.
|
||||
* This result should be freed (via PORT_Free) when no longer in use.
|
||||
* RETURN:
|
||||
* Returns SECSuccess when parsing was successful. Returns SECFailure when
|
||||
* problems were encountered.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_CheckOCSPStatus
|
||||
* Checks the status of a certificate via OCSP. Will only check status for
|
||||
* a certificate that has an AIA (Authority Information Access) extension
|
||||
* for OCSP *or* when a "default responder" is specified and enabled.
|
||||
* (If no AIA extension for OCSP and no default responder in place, the
|
||||
* cert is considered to have a good status and SECSuccess is returned.)
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* certificate DB of the cert that is being checked
|
||||
* CERTCertificate *cert
|
||||
* the certificate being checked
|
||||
* XXX in the long term also need a boolean parameter that specifies
|
||||
* whether to check the cert chain, as well; for now we check only
|
||||
* the leaf (the specified certificate)
|
||||
* PRTime time
|
||||
* time for which status is to be determined
|
||||
* void *pwArg
|
||||
* argument for password prompting, if needed
|
||||
* RETURN:
|
||||
* Returns SECSuccess if an approved OCSP responder "knows" the cert
|
||||
* *and* returns a non-revoked status for it; SECFailure otherwise,
|
||||
* with an error set describing the reason:
|
||||
*
|
||||
* SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
|
||||
* SEC_ERROR_OCSP_FUTURE_RESPONSE
|
||||
* SEC_ERROR_OCSP_MALFORMED_REQUEST
|
||||
* SEC_ERROR_OCSP_MALFORMED_RESPONSE
|
||||
* SEC_ERROR_OCSP_OLD_RESPONSE
|
||||
* SEC_ERROR_OCSP_REQUEST_NEEDS_SIG
|
||||
* SEC_ERROR_OCSP_SERVER_ERROR
|
||||
* SEC_ERROR_OCSP_TRY_SERVER_LATER
|
||||
* SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST
|
||||
* SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
|
||||
* SEC_ERROR_OCSP_UNKNOWN_CERT
|
||||
* SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS
|
||||
* SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE
|
||||
*
|
||||
* SEC_ERROR_BAD_SIGNATURE
|
||||
* SEC_ERROR_CERT_BAD_ACCESS_LOCATION
|
||||
* SEC_ERROR_INVALID_TIME
|
||||
* SEC_ERROR_REVOKED_CERTIFICATE
|
||||
* SEC_ERROR_UNKNOWN_ISSUER
|
||||
* SEC_ERROR_UNKNOWN_SIGNER
|
||||
*
|
||||
* Other errors are any of the many possible failures in cert verification
|
||||
* (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
|
||||
* verifying the signer's cert, or low-level problems (error allocating
|
||||
* memory, error performing ASN.1 decoding, etc.).
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
PRTime time, void *pwArg);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_CacheOCSPResponseFromSideChannel
|
||||
* First, this function checks the OCSP cache to see if a good response
|
||||
* for the given certificate already exists. If it does, then the function
|
||||
* returns successfully.
|
||||
*
|
||||
* If not, then it validates that the given OCSP response is a valid,
|
||||
* good response for the given certificate and inserts it into the
|
||||
* cache.
|
||||
*
|
||||
* This function is intended for use when OCSP responses are provided via a
|
||||
* side-channel, i.e. TLS OCSP stapling (a.k.a. the status_request extension).
|
||||
*
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* certificate DB of the cert that is being checked
|
||||
* CERTCertificate *cert
|
||||
* the certificate being checked
|
||||
* PRTime time
|
||||
* time for which status is to be determined
|
||||
* SECItem *encodedResponse
|
||||
* the DER encoded bytes of the OCSP response
|
||||
* void *pwArg
|
||||
* argument for password prompting, if needed
|
||||
* RETURN:
|
||||
* SECSuccess if the cert was found in the cache, or if the OCSP response was
|
||||
* found to be valid and inserted into the cache. SECFailure otherwise.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle,
|
||||
CERTCertificate *cert,
|
||||
PRTime time,
|
||||
const SECItem *encodedResponse,
|
||||
void *pwArg);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_GetOCSPStatusForCertID
|
||||
* Returns the OCSP status contained in the passed in parameter response
|
||||
* that corresponds to the certID passed in.
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* certificate DB of the cert that is being checked
|
||||
* CERTOCSPResponse *response
|
||||
* the OCSP response we want to retrieve status from.
|
||||
* CERTOCSPCertID *certID
|
||||
* the ID we want to look for from the response.
|
||||
* CERTCertificate *signerCert
|
||||
* the certificate that was used to sign the OCSP response.
|
||||
* must be obtained via a call to CERT_VerifyOCSPResponseSignature.
|
||||
* PRTime time
|
||||
* The time at which we're checking the status for.
|
||||
* RETURN:
|
||||
* Return values are the same as those for CERT_CheckOCSPStatus
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle,
|
||||
CERTOCSPResponse *response,
|
||||
CERTOCSPCertID *certID,
|
||||
CERTCertificate *signerCert,
|
||||
PRTime time);
|
||||
|
||||
/*
|
||||
* FUNCTION CERT_GetOCSPResponseStatus
|
||||
* Returns the response status for the response passed.
|
||||
* INPUTS:
|
||||
* CERTOCSPResponse *response
|
||||
* The response to query for status
|
||||
* RETURN:
|
||||
* Returns SECSuccess if the response has a successful status value.
|
||||
* Otherwise it returns SECFailure and sets one of the following error
|
||||
* codes via PORT_SetError
|
||||
* SEC_ERROR_OCSP_MALFORMED_REQUEST
|
||||
* SEC_ERROR_OCSP_SERVER_ERROR
|
||||
* SEC_ERROR_OCSP_TRY_SERVER_LATER
|
||||
* SEC_ERROR_OCSP_REQUEST_NEEDS_SIG
|
||||
* SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST
|
||||
* SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_GetOCSPResponseStatus(CERTOCSPResponse *response);
|
||||
|
||||
/*
|
||||
* FUNCTION CERT_CreateOCSPCertID
|
||||
* Returns the OCSP certID for the certificate passed in.
|
||||
* INPUTS:
|
||||
* CERTCertificate *cert
|
||||
* The certificate for which to create the certID for.
|
||||
* PRTime time
|
||||
* The time at which the id is requested for. This is used
|
||||
* to determine the appropriate issuer for the cert since
|
||||
* the issuing CA may be an older expired certificate.
|
||||
* RETURN:
|
||||
* A new copy of a CERTOCSPCertID*. The memory for this certID
|
||||
* should be freed by calling CERT_DestroyOCSPCertID when the
|
||||
* certID is no longer necessary.
|
||||
*/
|
||||
extern CERTOCSPCertID *
|
||||
CERT_CreateOCSPCertID(CERTCertificate *cert, PRTime time);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_DestroyOCSPCertID
|
||||
* Frees the memory associated with the certID passed in.
|
||||
* INPUTS:
|
||||
* CERTOCSPCertID* certID
|
||||
* The certID that the caller no longer needs and wants to
|
||||
* free the associated memory.
|
||||
* RETURN:
|
||||
* SECSuccess if freeing the memory was successful. Returns
|
||||
* SECFailure if the memory passed in was not allocated with
|
||||
* a call to CERT_CreateOCSPCertID.
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_DestroyOCSPCertID(CERTOCSPCertID *certID);
|
||||
|
||||
extern CERTOCSPSingleResponse *
|
||||
CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena,
|
||||
CERTOCSPCertID *id,
|
||||
PRTime thisUpdate,
|
||||
const PRTime *nextUpdate);
|
||||
|
||||
extern CERTOCSPSingleResponse *
|
||||
CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena,
|
||||
CERTOCSPCertID *id,
|
||||
PRTime thisUpdate,
|
||||
const PRTime *nextUpdate);
|
||||
|
||||
extern CERTOCSPSingleResponse *
|
||||
CERT_CreateOCSPSingleResponseRevoked(
|
||||
PLArenaPool *arena,
|
||||
CERTOCSPCertID *id,
|
||||
PRTime thisUpdate,
|
||||
const PRTime *nextUpdate,
|
||||
PRTime revocationTime,
|
||||
const CERTCRLEntryReasonCode *revocationReason);
|
||||
|
||||
extern SECItem *
|
||||
CERT_CreateEncodedOCSPSuccessResponse(
|
||||
PLArenaPool *arena,
|
||||
CERTCertificate *responderCert,
|
||||
CERTOCSPResponderIDType responderIDType,
|
||||
PRTime producedAt,
|
||||
CERTOCSPSingleResponse **responses,
|
||||
void *wincx);
|
||||
|
||||
/*
|
||||
* FUNCTION: CERT_CreateEncodedOCSPErrorResponse
|
||||
* Creates an encoded OCSP response with an error response status.
|
||||
* INPUTS:
|
||||
* PLArenaPool *arena
|
||||
* The return value is allocated from here.
|
||||
* If a NULL is passed in, allocation is done from the heap instead.
|
||||
* int error
|
||||
* An NSS error code indicating an error response status. The error
|
||||
* code is mapped to an OCSP response status as follows:
|
||||
* SEC_ERROR_OCSP_MALFORMED_REQUEST -> malformedRequest
|
||||
* SEC_ERROR_OCSP_SERVER_ERROR -> internalError
|
||||
* SEC_ERROR_OCSP_TRY_SERVER_LATER -> tryLater
|
||||
* SEC_ERROR_OCSP_REQUEST_NEEDS_SIG -> sigRequired
|
||||
* SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST -> unauthorized
|
||||
* where the OCSP response status is an enumerated type defined in
|
||||
* RFC 2560:
|
||||
* OCSPResponseStatus ::= ENUMERATED {
|
||||
* successful (0), --Response has valid confirmations
|
||||
* malformedRequest (1), --Illegal confirmation request
|
||||
* internalError (2), --Internal error in issuer
|
||||
* tryLater (3), --Try again later
|
||||
* --(4) is not used
|
||||
* sigRequired (5), --Must sign the request
|
||||
* unauthorized (6) --Request unauthorized
|
||||
* }
|
||||
* RETURN:
|
||||
* Returns a pointer to the SECItem holding the response.
|
||||
* On error, returns null with error set describing the reason:
|
||||
* SEC_ERROR_INVALID_ARGS
|
||||
* Other errors are low-level problems (no memory, bad database, etc.).
|
||||
*/
|
||||
extern SECItem *
|
||||
CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error);
|
||||
|
||||
/* Sends an OCSP request using the HTTP POST method to the location addressed
|
||||
* by the URL in |location| parameter. The request body will be
|
||||
* |encodedRequest|, which must be a valid encoded OCSP request. On success,
|
||||
* the server's response is returned and the caller must free it using
|
||||
* SECITEM_FreeItem. On failure, NULL is returned. No parsing or validation of
|
||||
* the HTTP response is done.
|
||||
*
|
||||
* If a default HTTP client has been registered with
|
||||
* SEC_RegisterDefaultHttpClient then that client is used. Otherwise, an
|
||||
* internal HTTP client is used.
|
||||
*/
|
||||
SECItem *CERT_PostOCSPRequest(PLArenaPool *arena, const char *location,
|
||||
const SECItem *encodedRequest);
|
||||
|
||||
/************************************************************************/
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _OCSP_H_ */
|
||||
166
security/nss/lib/certhigh/ocspi.h
Normal file
166
security/nss/lib/certhigh/ocspi.h
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* ocspi.h - NSS internal interfaces to OCSP code
|
||||
*/
|
||||
|
||||
#ifndef _OCSPI_H_
|
||||
#define _OCSPI_H_
|
||||
|
||||
SECStatus OCSP_InitGlobal(void);
|
||||
SECStatus OCSP_ShutdownGlobal(void);
|
||||
|
||||
ocspResponseData *
|
||||
ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER);
|
||||
|
||||
ocspSignature *
|
||||
ocsp_GetResponseSignature(CERTOCSPResponse *response);
|
||||
|
||||
SECItem *
|
||||
ocsp_DigestValue(PLArenaPool *arena, SECOidTag digestAlg,
|
||||
SECItem *fill, const SECItem *src);
|
||||
|
||||
PRBool
|
||||
ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert);
|
||||
|
||||
CERTCertificate *
|
||||
ocsp_GetSignerCertificate(CERTCertDBHandle *handle, ocspResponseData *tbsData,
|
||||
ocspSignature *signature, CERTCertificate *issuer);
|
||||
|
||||
SECStatus
|
||||
ocsp_VerifyResponseSignature(CERTCertificate *signerCert,
|
||||
ocspSignature *signature,
|
||||
SECItem *tbsResponseDataDER,
|
||||
void *pwArg);
|
||||
|
||||
CERTOCSPRequest *
|
||||
cert_CreateSingleCertOCSPRequest(CERTOCSPCertID *certID,
|
||||
CERTCertificate *singleCert,
|
||||
PRTime time,
|
||||
PRBool addServiceLocator,
|
||||
CERTCertificate *signerCert);
|
||||
|
||||
typedef enum { ocspMissing,
|
||||
ocspFresh,
|
||||
ocspStale } OCSPFreshness;
|
||||
|
||||
SECStatus
|
||||
ocsp_GetCachedOCSPResponseStatus(CERTOCSPCertID *certID,
|
||||
PRTime time,
|
||||
PRBool ignoreOcspFailureMode,
|
||||
SECStatus *rvOcsp,
|
||||
SECErrorCodes *missingResponseError,
|
||||
OCSPFreshness *freshness);
|
||||
|
||||
/*
|
||||
* FUNCTION: cert_ProcessOCSPResponse
|
||||
* Same behavior and basic parameters as CERT_GetOCSPStatusForCertID.
|
||||
* In addition it can update the OCSP cache (using information
|
||||
* available internally to this function).
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* certificate DB of the cert that is being checked
|
||||
* CERTOCSPResponse *response
|
||||
* the OCSP response we want to retrieve status from.
|
||||
* CERTOCSPCertID *certID
|
||||
* the ID we want to look for from the response.
|
||||
* CERTCertificate *signerCert
|
||||
* the certificate that was used to sign the OCSP response.
|
||||
* must be obtained via a call to CERT_VerifyOCSPResponseSignature.
|
||||
* PRTime time
|
||||
* The time at which we're checking the status for.
|
||||
* PRBool *certIDWasConsumed
|
||||
* In and Out parameter.
|
||||
* If certIDWasConsumed is NULL on input,
|
||||
* this function might produce a deep copy of cert ID
|
||||
* for storing it in the cache.
|
||||
* If out value is true, ownership of parameter certID was
|
||||
* transferred to the OCSP cache.
|
||||
* SECStatus *cacheUpdateStatus
|
||||
* This optional out parameter will contain the result
|
||||
* of the cache update operation (if requested).
|
||||
* RETURN:
|
||||
* The return value is not influenced by the cache operation,
|
||||
* it matches the documentation for CERT_CheckOCSPStatus
|
||||
*/
|
||||
|
||||
SECStatus
|
||||
cert_ProcessOCSPResponse(CERTCertDBHandle *handle,
|
||||
CERTOCSPResponse *response,
|
||||
CERTOCSPCertID *certID,
|
||||
CERTCertificate *signerCert,
|
||||
PRTime time,
|
||||
PRBool *certIDWasConsumed,
|
||||
SECStatus *cacheUpdateStatus);
|
||||
|
||||
/*
|
||||
* FUNCTION: cert_RememberOCSPProcessingFailure
|
||||
* If an application notices a failure during OCSP processing,
|
||||
* it should finally call this function. The failure will be recorded
|
||||
* in the OCSP cache in order to avoid repetitive failures.
|
||||
* INPUTS:
|
||||
* CERTOCSPCertID *certID
|
||||
* the ID that was used for the failed OCSP processing
|
||||
* PRBool *certIDWasConsumed
|
||||
* Out parameter, if set to true, ownership of parameter certID was
|
||||
* transferred to the OCSP cache.
|
||||
* RETURN:
|
||||
* Status of the cache update operation.
|
||||
*/
|
||||
|
||||
SECStatus
|
||||
cert_RememberOCSPProcessingFailure(CERTOCSPCertID *certID,
|
||||
PRBool *certIDWasConsumed);
|
||||
|
||||
/*
|
||||
* FUNCTION: ocsp_GetResponderLocation
|
||||
* Check ocspx context for user-designated responder URI first. If not
|
||||
* found, checks cert AIA extension.
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* certificate DB of the cert that is being checked
|
||||
* CERTCertificate *cert
|
||||
* The certificate being examined.
|
||||
* PRBool *certIDWasConsumed
|
||||
* Out parameter, if set to true, URI of default responder is
|
||||
* returned.
|
||||
* RETURN:
|
||||
* Responder URI.
|
||||
*/
|
||||
char *
|
||||
ocsp_GetResponderLocation(CERTCertDBHandle *handle,
|
||||
CERTCertificate *cert,
|
||||
PRBool canUseDefaultLocation,
|
||||
PRBool *isDefault);
|
||||
|
||||
/* FUNCTION: ocsp_FetchingFailureIsVerificationFailure
|
||||
* The function checks the global ocsp settings and
|
||||
* tells how to treat an ocsp response fetching failure.
|
||||
* RETURNS:
|
||||
* if PR_TRUE is returned, then treat fetching as a
|
||||
* revoked cert status.
|
||||
*/
|
||||
PRBool
|
||||
ocsp_FetchingFailureIsVerificationFailure(void);
|
||||
|
||||
size_t
|
||||
ocsp_UrlEncodeBase64Buf(const char *base64Buf, char *outputBuf);
|
||||
|
||||
SECStatus
|
||||
ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
|
||||
CERTOCSPResponse *response,
|
||||
CERTOCSPCertID *certID,
|
||||
CERTCertificate *signerCert,
|
||||
PRTime time,
|
||||
CERTOCSPSingleResponse **pSingleResponse);
|
||||
|
||||
SECStatus
|
||||
ocsp_CertHasGoodStatus(ocspCertStatus *status, PRTime time);
|
||||
|
||||
void
|
||||
ocsp_CacheSingleResponse(CERTOCSPCertID *certID,
|
||||
CERTOCSPSingleResponse *single,
|
||||
PRBool *certIDWasConsumed);
|
||||
|
||||
#endif /* _OCSPI_H_ */
|
||||
597
security/nss/lib/certhigh/ocspsig.c
Normal file
597
security/nss/lib/certhigh/ocspsig.c
Normal file
|
|
@ -0,0 +1,597 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "plarena.h"
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secitem.h"
|
||||
#include "secasn1.h"
|
||||
#include "secder.h"
|
||||
#include "cert.h"
|
||||
#include "secerr.h"
|
||||
#include "secoid.h"
|
||||
#include "sechash.h"
|
||||
#include "keyhi.h"
|
||||
#include "cryptohi.h"
|
||||
#include "ocsp.h"
|
||||
#include "ocspti.h"
|
||||
#include "ocspi.h"
|
||||
#include "pk11pub.h"
|
||||
|
||||
extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[];
|
||||
extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[];
|
||||
extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[];
|
||||
|
||||
ocspCertStatus *
|
||||
ocsp_CreateCertStatus(PLArenaPool *arena,
|
||||
ocspCertStatusType status,
|
||||
PRTime revocationTime)
|
||||
{
|
||||
ocspCertStatus *cs;
|
||||
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case ocspCertStatus_good:
|
||||
case ocspCertStatus_unknown:
|
||||
case ocspCertStatus_revoked:
|
||||
break;
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cs = PORT_ArenaZNew(arena, ocspCertStatus);
|
||||
if (!cs)
|
||||
return NULL;
|
||||
cs->certStatusType = status;
|
||||
switch (status) {
|
||||
case ocspCertStatus_good:
|
||||
cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0);
|
||||
if (!cs->certStatusInfo.goodInfo)
|
||||
return NULL;
|
||||
break;
|
||||
case ocspCertStatus_unknown:
|
||||
cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0);
|
||||
if (!cs->certStatusInfo.unknownInfo)
|
||||
return NULL;
|
||||
break;
|
||||
case ocspCertStatus_revoked:
|
||||
cs->certStatusInfo.revokedInfo =
|
||||
PORT_ArenaZNew(arena, ocspRevokedInfo);
|
||||
if (!cs->certStatusInfo.revokedInfo)
|
||||
return NULL;
|
||||
cs->certStatusInfo.revokedInfo->revocationReason =
|
||||
SECITEM_AllocItem(arena, NULL, 0);
|
||||
if (!cs->certStatusInfo.revokedInfo->revocationReason)
|
||||
return NULL;
|
||||
if (DER_TimeToGeneralizedTimeArena(arena,
|
||||
&cs->certStatusInfo.revokedInfo->revocationTime,
|
||||
revocationTime) !=
|
||||
SECSuccess)
|
||||
return NULL;
|
||||
break;
|
||||
default:
|
||||
PORT_Assert(PR_FALSE);
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
|
||||
static const SEC_ASN1Template mySEC_EnumeratedTemplate[] = {
|
||||
{ SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = {
|
||||
{ SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = {
|
||||
{ SEC_ASN1_GENERALIZED_TIME,
|
||||
offsetof(ocspRevokedInfo, revocationTime) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
|
||||
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(ocspRevokedInfo, revocationReason),
|
||||
mySEC_PointerToEnumeratedTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = {
|
||||
{ SEC_ASN1_POINTER, 0,
|
||||
ocsp_EncodeRevokedInfoTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_NullTemplate[] = {
|
||||
{ SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template ocsp_CertStatusTemplate[] = {
|
||||
{ SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType),
|
||||
0, sizeof(ocspCertStatus) },
|
||||
{ SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
0, mySEC_NullTemplate, ocspCertStatus_good },
|
||||
{ SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
||||
offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
|
||||
ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked },
|
||||
{ SEC_ASN1_CONTEXT_SPECIFIC | 2,
|
||||
0, mySEC_NullTemplate, ocspCertStatus_unknown },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(SECAlgorithmID) },
|
||||
{ SEC_ASN1_OBJECT_ID,
|
||||
offsetof(SECAlgorithmID, algorithm) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
|
||||
offsetof(SECAlgorithmID, parameters) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_AnyTemplate[] = {
|
||||
{ SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = {
|
||||
{ SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_IntegerTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = {
|
||||
{ SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = {
|
||||
{ SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = {
|
||||
{ SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template ocsp_myCertIDTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(CERTOCSPCertID) },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(CERTOCSPCertID, hashAlgorithm),
|
||||
mySECOID_AlgorithmIDTemplate },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(CERTOCSPCertID, issuerNameHash) },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(CERTOCSPCertID, issuerKeyHash) },
|
||||
{ SEC_ASN1_INTEGER,
|
||||
offsetof(CERTOCSPCertID, serialNumber) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(CERTCertExtension) },
|
||||
{ SEC_ASN1_OBJECT_ID,
|
||||
offsetof(CERTCertExtension, id) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */
|
||||
offsetof(CERTCertExtension, critical) },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(CERTCertExtension, value) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[] = {
|
||||
{ SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(CERTOCSPSingleResponse) },
|
||||
{ SEC_ASN1_POINTER,
|
||||
offsetof(CERTOCSPSingleResponse, certID),
|
||||
ocsp_myCertIDTemplate },
|
||||
{ SEC_ASN1_ANY,
|
||||
offsetof(CERTOCSPSingleResponse, derCertStatus) },
|
||||
{ SEC_ASN1_GENERALIZED_TIME,
|
||||
offsetof(CERTOCSPSingleResponse, thisUpdate) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
|
||||
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(CERTOCSPSingleResponse, nextUpdate),
|
||||
mySEC_PointerToGeneralizedTimeTemplate },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
|
||||
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
||||
offsetof(CERTOCSPSingleResponse, singleExtensions),
|
||||
myCERT_PointerToSequenceOfCertExtensionTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(ocspResponseData) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
|
||||
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(ocspResponseData, version),
|
||||
mySEC_PointerToIntegerTemplate },
|
||||
{ SEC_ASN1_ANY,
|
||||
offsetof(ocspResponseData, derResponderID) },
|
||||
{ SEC_ASN1_GENERALIZED_TIME,
|
||||
offsetof(ocspResponseData, producedAt) },
|
||||
{ SEC_ASN1_SEQUENCE_OF,
|
||||
offsetof(ocspResponseData, responses),
|
||||
ocsp_mySingleResponseTemplate },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
|
||||
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
||||
offsetof(ocspResponseData, responseExtensions),
|
||||
myCERT_PointerToSequenceOfCertExtensionTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(ocspBasicOCSPResponse) },
|
||||
{ SEC_ASN1_POINTER,
|
||||
offsetof(ocspBasicOCSPResponse, tbsResponseData),
|
||||
ocsp_myResponseDataTemplate },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
|
||||
mySECOID_AlgorithmIDTemplate },
|
||||
{ SEC_ASN1_BIT_STRING,
|
||||
offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
|
||||
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
|
||||
mySEC_PointerToSequenceOfAnyTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static CERTOCSPSingleResponse *
|
||||
ocsp_CreateSingleResponse(PLArenaPool *arena,
|
||||
CERTOCSPCertID *id, ocspCertStatus *status,
|
||||
PRTime thisUpdate, const PRTime *nextUpdate)
|
||||
{
|
||||
CERTOCSPSingleResponse *sr;
|
||||
|
||||
if (!arena || !id || !status) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse);
|
||||
if (!sr)
|
||||
return NULL;
|
||||
sr->arena = arena;
|
||||
sr->certID = id;
|
||||
sr->certStatus = status;
|
||||
if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate) !=
|
||||
SECSuccess)
|
||||
return NULL;
|
||||
sr->nextUpdate = NULL;
|
||||
if (nextUpdate) {
|
||||
sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0);
|
||||
if (!sr->nextUpdate)
|
||||
return NULL;
|
||||
if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate) !=
|
||||
SECSuccess)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension *, 1);
|
||||
if (!sr->singleExtensions)
|
||||
return NULL;
|
||||
|
||||
sr->singleExtensions[0] = NULL;
|
||||
|
||||
if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus,
|
||||
status, ocsp_CertStatusTemplate))
|
||||
return NULL;
|
||||
|
||||
return sr;
|
||||
}
|
||||
|
||||
CERTOCSPSingleResponse *
|
||||
CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena,
|
||||
CERTOCSPCertID *id,
|
||||
PRTime thisUpdate,
|
||||
const PRTime *nextUpdate)
|
||||
{
|
||||
ocspCertStatus *cs;
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0);
|
||||
if (!cs)
|
||||
return NULL;
|
||||
return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
|
||||
}
|
||||
|
||||
CERTOCSPSingleResponse *
|
||||
CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena,
|
||||
CERTOCSPCertID *id,
|
||||
PRTime thisUpdate,
|
||||
const PRTime *nextUpdate)
|
||||
{
|
||||
ocspCertStatus *cs;
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0);
|
||||
if (!cs)
|
||||
return NULL;
|
||||
return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
|
||||
}
|
||||
|
||||
CERTOCSPSingleResponse *
|
||||
CERT_CreateOCSPSingleResponseRevoked(
|
||||
PLArenaPool *arena,
|
||||
CERTOCSPCertID *id,
|
||||
PRTime thisUpdate,
|
||||
const PRTime *nextUpdate,
|
||||
PRTime revocationTime,
|
||||
const CERTCRLEntryReasonCode *revocationReason)
|
||||
{
|
||||
ocspCertStatus *cs;
|
||||
/* revocationReason is not yet supported, so it must be NULL. */
|
||||
if (!arena || revocationReason) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime);
|
||||
if (!cs)
|
||||
return NULL;
|
||||
return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
|
||||
}
|
||||
|
||||
/* responderCert == 0 means:
|
||||
* create a response with an invalid signature (for testing purposes) */
|
||||
SECItem *
|
||||
CERT_CreateEncodedOCSPSuccessResponse(
|
||||
PLArenaPool *arena,
|
||||
CERTCertificate *responderCert,
|
||||
CERTOCSPResponderIDType responderIDType,
|
||||
PRTime producedAt,
|
||||
CERTOCSPSingleResponse **responses,
|
||||
void *wincx)
|
||||
{
|
||||
PLArenaPool *tmpArena;
|
||||
ocspResponseData *rd = NULL;
|
||||
ocspResponderID *rid = NULL;
|
||||
const SEC_ASN1Template *responderIDTemplate = NULL;
|
||||
ocspBasicOCSPResponse *br = NULL;
|
||||
ocspResponseBytes *rb = NULL;
|
||||
CERTOCSPResponse *response = NULL;
|
||||
|
||||
SECOidTag algID;
|
||||
SECOidData *od = NULL;
|
||||
SECKEYPrivateKey *privKey = NULL;
|
||||
SECItem *result = NULL;
|
||||
|
||||
if (!arena || !responses) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
if (responderIDType != ocspResponderID_byName &&
|
||||
responderIDType != ocspResponderID_byKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (!tmpArena)
|
||||
return NULL;
|
||||
|
||||
rd = PORT_ArenaZNew(tmpArena, ocspResponseData);
|
||||
if (!rd)
|
||||
goto done;
|
||||
rid = PORT_ArenaZNew(tmpArena, ocspResponderID);
|
||||
if (!rid)
|
||||
goto done;
|
||||
br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse);
|
||||
if (!br)
|
||||
goto done;
|
||||
rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes);
|
||||
if (!rb)
|
||||
goto done;
|
||||
response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse);
|
||||
if (!response)
|
||||
goto done;
|
||||
|
||||
rd->version.data = NULL;
|
||||
rd->version.len = 0;
|
||||
rd->responseExtensions = NULL;
|
||||
rd->responses = responses;
|
||||
if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) !=
|
||||
SECSuccess)
|
||||
goto done;
|
||||
|
||||
if (!responderCert) {
|
||||
/* use invalid signature for testing purposes */
|
||||
unsigned char dummyChar = 'd';
|
||||
SECItem dummy;
|
||||
|
||||
dummy.len = 1;
|
||||
dummy.data = &dummyChar;
|
||||
|
||||
/* it's easier to produdce a keyHash out of nowhere,
|
||||
* than to produce an encoded subject,
|
||||
* so for our dummy response we always use byKey
|
||||
*/
|
||||
|
||||
rid->responderIDType = ocspResponderID_byKey;
|
||||
if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash,
|
||||
&dummy))
|
||||
goto done;
|
||||
|
||||
if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
|
||||
ocsp_ResponderIDByKeyTemplate))
|
||||
goto done;
|
||||
|
||||
br->tbsResponseData = rd;
|
||||
|
||||
if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
|
||||
ocsp_myResponseDataTemplate))
|
||||
goto done;
|
||||
|
||||
br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem *, 1);
|
||||
if (!br->responseSignature.derCerts)
|
||||
goto done;
|
||||
br->responseSignature.derCerts[0] = NULL;
|
||||
|
||||
algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1);
|
||||
if (algID == SEC_OID_UNKNOWN)
|
||||
goto done;
|
||||
|
||||
/* match the regular signature code, which doesn't use the arena */
|
||||
if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1))
|
||||
goto done;
|
||||
PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1);
|
||||
|
||||
/* convert len-in-bytes to len-in-bits */
|
||||
br->responseSignature.signature.len = br->responseSignature.signature.len << 3;
|
||||
} else {
|
||||
rid->responderIDType = responderIDType;
|
||||
if (responderIDType == ocspResponderID_byName) {
|
||||
responderIDTemplate = ocsp_ResponderIDByNameTemplate;
|
||||
if (CERT_CopyName(tmpArena, &rid->responderIDValue.name,
|
||||
&responderCert->subject) != SECSuccess)
|
||||
goto done;
|
||||
} else {
|
||||
responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
|
||||
if (!CERT_GetSubjectPublicKeyDigest(tmpArena, responderCert,
|
||||
SEC_OID_SHA1, &rid->responderIDValue.keyHash))
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
|
||||
responderIDTemplate))
|
||||
goto done;
|
||||
|
||||
br->tbsResponseData = rd;
|
||||
|
||||
if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
|
||||
ocsp_myResponseDataTemplate))
|
||||
goto done;
|
||||
|
||||
br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem *, 1);
|
||||
if (!br->responseSignature.derCerts)
|
||||
goto done;
|
||||
br->responseSignature.derCerts[0] = NULL;
|
||||
|
||||
privKey = PK11_FindKeyByAnyCert(responderCert, wincx);
|
||||
if (!privKey)
|
||||
goto done;
|
||||
|
||||
algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1);
|
||||
if (algID == SEC_OID_UNKNOWN)
|
||||
goto done;
|
||||
|
||||
if (SEC_SignData(&br->responseSignature.signature,
|
||||
br->tbsResponseDataDER.data, br->tbsResponseDataDER.len,
|
||||
privKey, algID) !=
|
||||
SECSuccess)
|
||||
goto done;
|
||||
|
||||
/* convert len-in-bytes to len-in-bits */
|
||||
br->responseSignature.signature.len = br->responseSignature.signature.len << 3;
|
||||
|
||||
/* br->responseSignature.signature wasn't allocated from arena,
|
||||
* we must free it when done. */
|
||||
}
|
||||
|
||||
if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0) !=
|
||||
SECSuccess)
|
||||
goto done;
|
||||
|
||||
if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br,
|
||||
ocsp_EncodeBasicOCSPResponseTemplate))
|
||||
goto done;
|
||||
|
||||
rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE;
|
||||
|
||||
od = SECOID_FindOIDByTag(rb->responseTypeTag);
|
||||
if (!od)
|
||||
goto done;
|
||||
|
||||
rb->responseType = od->oid;
|
||||
rb->decodedResponse.basic = br;
|
||||
|
||||
response->arena = tmpArena;
|
||||
response->responseBytes = rb;
|
||||
response->statusValue = ocspResponse_successful;
|
||||
|
||||
if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus,
|
||||
response->statusValue))
|
||||
goto done;
|
||||
|
||||
result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate);
|
||||
|
||||
done:
|
||||
if (privKey)
|
||||
SECKEY_DestroyPrivateKey(privKey);
|
||||
if (br && br->responseSignature.signature.data)
|
||||
SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE);
|
||||
PORT_FreeArena(tmpArena, PR_FALSE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(CERTOCSPResponse) },
|
||||
{ SEC_ASN1_ENUMERATED,
|
||||
offsetof(CERTOCSPResponse, responseStatus) },
|
||||
{ 0, 0,
|
||||
mySEC_NullTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
SECItem *
|
||||
CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error)
|
||||
{
|
||||
CERTOCSPResponse response;
|
||||
SECItem *result = NULL;
|
||||
|
||||
switch (error) {
|
||||
case SEC_ERROR_OCSP_MALFORMED_REQUEST:
|
||||
response.statusValue = ocspResponse_malformedRequest;
|
||||
break;
|
||||
case SEC_ERROR_OCSP_SERVER_ERROR:
|
||||
response.statusValue = ocspResponse_internalError;
|
||||
break;
|
||||
case SEC_ERROR_OCSP_TRY_SERVER_LATER:
|
||||
response.statusValue = ocspResponse_tryLater;
|
||||
break;
|
||||
case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG:
|
||||
response.statusValue = ocspResponse_sigRequired;
|
||||
break;
|
||||
case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST:
|
||||
response.statusValue = ocspResponse_unauthorized;
|
||||
break;
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus,
|
||||
response.statusValue))
|
||||
return NULL;
|
||||
|
||||
result = SEC_ASN1EncodeItem(arena, NULL, &response,
|
||||
ocsp_OCSPErrorResponseTemplate);
|
||||
|
||||
SECITEM_FreeItem(&response.responseStatus, PR_FALSE);
|
||||
|
||||
return result;
|
||||
}
|
||||
301
security/nss/lib/certhigh/ocspt.h
Normal file
301
security/nss/lib/certhigh/ocspt.h
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Public header for exported OCSP types.
|
||||
*/
|
||||
|
||||
#ifndef _OCSPT_H_
|
||||
#define _OCSPT_H_
|
||||
|
||||
/*
|
||||
* The following are all opaque types. If someone needs to get at
|
||||
* a field within, then we need to fix the API. Try very hard not
|
||||
* make the type available to them.
|
||||
*/
|
||||
typedef struct CERTOCSPRequestStr CERTOCSPRequest;
|
||||
typedef struct CERTOCSPResponseStr CERTOCSPResponse;
|
||||
|
||||
/*
|
||||
* XXX I think only those first two above should need to be exported,
|
||||
* but until I know for certain I am leaving the rest of these here, too.
|
||||
*/
|
||||
typedef struct CERTOCSPCertIDStr CERTOCSPCertID;
|
||||
typedef struct CERTOCSPSingleResponseStr CERTOCSPSingleResponse;
|
||||
|
||||
/*
|
||||
* This interface is described in terms of an HttpClient which
|
||||
* supports at least a specified set of functions. (An implementer may
|
||||
* provide HttpClients with additional functionality accessible only to
|
||||
* users with a particular implementation in mind.) The basic behavior
|
||||
* is provided by defining a set of functions, listed in an
|
||||
* SEC_HttpServerFcnStruct. If the implementor of a SpecificHttpClient
|
||||
* registers his SpecificHttpClient as the default HttpClient, then his
|
||||
* functions will be called by the user of an HttpClient, such as an
|
||||
* OCSPChecker.
|
||||
*
|
||||
* The implementer of a specific HttpClient (e.g., the NSS-provided
|
||||
* DefaultHttpClient), populates an SEC_HttpClientFcnStruct, uses it to
|
||||
* register his client, and waits for his functions to be called.
|
||||
*
|
||||
* For future expandability, the SEC_HttpClientFcnStruct is defined as a
|
||||
* union, with the version field acting as a selector. The proposed
|
||||
* initial version of the structure is given following the definition
|
||||
* of the union. The HttpClientState structure is implementation-
|
||||
* dependent, and should be opaque to the user.
|
||||
*/
|
||||
|
||||
typedef void *SEC_HTTP_SERVER_SESSION;
|
||||
typedef void *SEC_HTTP_REQUEST_SESSION;
|
||||
|
||||
/*
|
||||
* This function creates a SEC_HTTP_SERVER_SESSION object. The implementer of a
|
||||
* specific HttpClient will allocate the necessary space, when this
|
||||
* function is called, and will free it when the corresponding FreeFcn
|
||||
* is called. The SEC_HTTP_SERVER_SESSION object is passed, as an opaque object,
|
||||
* to subsequent calls.
|
||||
*
|
||||
* If the function returns SECSuccess, the returned SEC_HTTP_SERVER_SESSION
|
||||
* must be cleaned up with a call to SEC_HttpServer_FreeSession,
|
||||
* after processing is finished.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpServer_CreateSessionFcn)(
|
||||
const char *host,
|
||||
PRUint16 portnum,
|
||||
SEC_HTTP_SERVER_SESSION *pSession);
|
||||
|
||||
/*
|
||||
* This function is called to allow the implementation to attempt to keep
|
||||
* the connection alive. Depending on the underlying platform, it might
|
||||
* immediately return SECSuccess without having performed any operations.
|
||||
* (If a connection has not been kept alive, a subsequent call to
|
||||
* SEC_HttpRequest_TrySendAndReceiveFcn should reopen the connection
|
||||
* automatically.)
|
||||
*
|
||||
* If the connection uses nonblocking I/O, this function may return
|
||||
* SECWouldBlock and store a nonzero value at "pPollDesc". In that case
|
||||
* the caller may wait on the poll descriptor, and should call this function
|
||||
* again until SECSuccess (and a zero value at "pPollDesc") is obtained.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpServer_KeepAliveSessionFcn)(
|
||||
SEC_HTTP_SERVER_SESSION session,
|
||||
PRPollDesc **pPollDesc);
|
||||
|
||||
/*
|
||||
* This function frees the client SEC_HTTP_SERVER_SESSION object, closes all
|
||||
* SEC_HTTP_REQUEST_SESSIONs created for that server, discards all partial results,
|
||||
* frees any memory that was allocated by the client, and invalidates any
|
||||
* response pointers that might have been returned by prior server or request
|
||||
* functions.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpServer_FreeSessionFcn)(
|
||||
SEC_HTTP_SERVER_SESSION session);
|
||||
|
||||
/*
|
||||
* This function creates a SEC_HTTP_REQUEST_SESSION object. The implementer of a
|
||||
* specific HttpClient will allocate the necessary space, when this
|
||||
* function is called, and will free it when the corresponding FreeFcn
|
||||
* is called. The SEC_HTTP_REQUEST_SESSION object is passed, as an opaque object,
|
||||
* to subsequent calls.
|
||||
*
|
||||
* An implementation that does not support the requested protocol variant
|
||||
* (usually "http", but could eventually allow "https") or request method
|
||||
* should return SECFailure.
|
||||
*
|
||||
* Timeout values may include the constants PR_INTERVAL_NO_TIMEOUT (wait
|
||||
* forever) or PR_INTERVAL_NO_WAIT (nonblocking I/O).
|
||||
*
|
||||
* If the function returns SECSuccess, the returned SEC_HTTP_REQUEST_SESSION
|
||||
* must be cleaned up with a call to SEC_HttpRequest_FreeSession,
|
||||
* after processing is finished.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpRequest_CreateFcn)(
|
||||
SEC_HTTP_SERVER_SESSION session,
|
||||
const char *http_protocol_variant, /* usually "http" */
|
||||
const char *path_and_query_string,
|
||||
const char *http_request_method,
|
||||
const PRIntervalTime timeout,
|
||||
SEC_HTTP_REQUEST_SESSION *pRequest);
|
||||
|
||||
/*
|
||||
* This function sets data to be sent to the server for an HTTP request
|
||||
* of http_request_method == POST. If a particular implementation
|
||||
* supports it, the details for the POST request can be set by calling
|
||||
* this function, prior to activating the request with TrySendAndReceiveFcn.
|
||||
*
|
||||
* An implementation that does not support the POST method should
|
||||
* implement a SetPostDataFcn function that returns immediately.
|
||||
*
|
||||
* Setting http_content_type is optional, the parameter may
|
||||
* by NULL or the empty string.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpRequest_SetPostDataFcn)(
|
||||
SEC_HTTP_REQUEST_SESSION request,
|
||||
const char *http_data,
|
||||
const PRUint32 http_data_len,
|
||||
const char *http_content_type);
|
||||
|
||||
/*
|
||||
* This function sets an additional HTTP protocol request header.
|
||||
* If a particular implementation supports it, one or multiple headers
|
||||
* can be added to the request by calling this function once or multiple
|
||||
* times, prior to activating the request with TryFcn.
|
||||
*
|
||||
* An implementation that does not support setting additional headers
|
||||
* should implement an AddRequestHeaderFcn function that returns immediately.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpRequest_AddHeaderFcn)(
|
||||
SEC_HTTP_REQUEST_SESSION request,
|
||||
const char *http_header_name,
|
||||
const char *http_header_value);
|
||||
|
||||
/*
|
||||
* This function initiates or continues an HTTP request. After
|
||||
* parameters have been set with the Create function and, optionally,
|
||||
* modified or enhanced with the AddParams function, this call creates
|
||||
* the socket connection and initiates the communication.
|
||||
*
|
||||
* If a timeout value of zero is specified, indicating non-blocking
|
||||
* I/O, the client creates a non-blocking socket, and returns a status
|
||||
* of SECWouldBlock and a non-NULL PRPollDesc if the operation is not
|
||||
* complete. In that case all other return parameters are undefined.
|
||||
* The caller is expected to repeat the call, possibly after using
|
||||
* PRPoll to determine that a completion has occurred, until a return
|
||||
* value of SECSuccess (and a NULL value for pPollDesc) or a return
|
||||
* value of SECFailure (indicating failure on the network level)
|
||||
* is obtained.
|
||||
*
|
||||
* http_response_data_len is both input and output parameter.
|
||||
* If a pointer to a PRUint32 is supplied, the http client is
|
||||
* expected to check the given integer value and always set an out
|
||||
* value, even on failure.
|
||||
* An input value of zero means, the caller will accept any response len.
|
||||
* A different input value indicates the maximum response value acceptable
|
||||
* to the caller.
|
||||
* If data is successfully read and the size is acceptable to the caller,
|
||||
* the function will return SECSuccess and set http_response_data_len to
|
||||
* the size of the block returned in http_response_data.
|
||||
* If the data read from the http server is larger than the acceptable
|
||||
* size, the function will return SECFailure.
|
||||
* http_response_data_len will be set to a value different from zero to
|
||||
* indicate the reason of the failure.
|
||||
* An out value of "0" means, the failure was unrelated to the
|
||||
* acceptable size.
|
||||
* An out value of "1" means, the result data is larger than the
|
||||
* accpeptable size, but the real size is not yet known to the http client
|
||||
* implementation and it stopped retrieving it,
|
||||
* Any other out value combined with a return value of SECFailure
|
||||
* will indicate the actual size of the server data.
|
||||
*
|
||||
* The caller is permitted to provide NULL values for any of the
|
||||
* http_response arguments, indicating the caller is not interested in
|
||||
* those values. If the caller does provide an address, the HttpClient
|
||||
* stores at that address a pointer to the corresponding argument, at
|
||||
* the completion of the operation.
|
||||
*
|
||||
* All returned pointers will be owned by the the HttpClient
|
||||
* implementation and will remain valid until the call to
|
||||
* SEC_HttpRequest_FreeFcn.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpRequest_TrySendAndReceiveFcn)(
|
||||
SEC_HTTP_REQUEST_SESSION request,
|
||||
PRPollDesc **pPollDesc,
|
||||
PRUint16 *http_response_code,
|
||||
const char **http_response_content_type,
|
||||
const char **http_response_headers,
|
||||
const char **http_response_data,
|
||||
PRUint32 *http_response_data_len);
|
||||
|
||||
/*
|
||||
* Calling CancelFcn asks for premature termination of the request.
|
||||
*
|
||||
* Future calls to SEC_HttpRequest_TrySendAndReceive should
|
||||
* by avoided, but in this case the HttpClient implementation
|
||||
* is expected to return immediately with SECFailure.
|
||||
*
|
||||
* After calling CancelFcn, a separate call to SEC_HttpRequest_FreeFcn
|
||||
* is still necessary to free resources.
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpRequest_CancelFcn)(
|
||||
SEC_HTTP_REQUEST_SESSION request);
|
||||
|
||||
/*
|
||||
* Before calling this function, it must be assured the request
|
||||
* has been completed, i.e. either SEC_HttpRequest_TrySendAndReceiveFcn has
|
||||
* returned SECSuccess, or the request has been canceled with
|
||||
* a call to SEC_HttpRequest_CancelFcn.
|
||||
*
|
||||
* This function frees the client state object, closes all sockets,
|
||||
* discards all partial results, frees any memory that was allocated
|
||||
* by the client, and invalidates all response pointers that might
|
||||
* have been returned by SEC_HttpRequest_TrySendAndReceiveFcn
|
||||
*/
|
||||
typedef SECStatus (*SEC_HttpRequest_FreeFcn)(
|
||||
SEC_HTTP_REQUEST_SESSION request);
|
||||
|
||||
typedef struct SEC_HttpClientFcnV1Struct {
|
||||
SEC_HttpServer_CreateSessionFcn createSessionFcn;
|
||||
SEC_HttpServer_KeepAliveSessionFcn keepAliveSessionFcn;
|
||||
SEC_HttpServer_FreeSessionFcn freeSessionFcn;
|
||||
SEC_HttpRequest_CreateFcn createFcn;
|
||||
SEC_HttpRequest_SetPostDataFcn setPostDataFcn;
|
||||
SEC_HttpRequest_AddHeaderFcn addHeaderFcn;
|
||||
SEC_HttpRequest_TrySendAndReceiveFcn trySendAndReceiveFcn;
|
||||
SEC_HttpRequest_CancelFcn cancelFcn;
|
||||
SEC_HttpRequest_FreeFcn freeFcn;
|
||||
} SEC_HttpClientFcnV1;
|
||||
|
||||
typedef struct SEC_HttpClientFcnStruct {
|
||||
PRInt16 version;
|
||||
union {
|
||||
SEC_HttpClientFcnV1 ftable1;
|
||||
/* SEC_HttpClientFcnV2 ftable2; */
|
||||
/* ... */
|
||||
} fcnTable;
|
||||
} SEC_HttpClientFcn;
|
||||
|
||||
/*
|
||||
* ocspMode_FailureIsVerificationFailure:
|
||||
* This is the classic behaviour of NSS.
|
||||
* Any OCSP failure is a verification failure (classic mode, default).
|
||||
* Without a good response, OCSP networking will be retried each time
|
||||
* it is required for verifying a cert.
|
||||
*
|
||||
* ocspMode_FailureIsNotAVerificationFailure:
|
||||
* If we fail to obtain a valid OCSP response, consider the
|
||||
* cert as good.
|
||||
* Failed OCSP attempts might get cached and not retried until
|
||||
* minimumSecondsToNextFetchAttempt.
|
||||
* If we are able to obtain a valid response, the cert
|
||||
* will be considered good, if either status is "good"
|
||||
* or the cert was not yet revoked at verification time.
|
||||
*
|
||||
* Additional failure modes might be added in the future.
|
||||
*/
|
||||
typedef enum {
|
||||
ocspMode_FailureIsVerificationFailure = 0,
|
||||
ocspMode_FailureIsNotAVerificationFailure = 1
|
||||
} SEC_OcspFailureMode;
|
||||
|
||||
/*
|
||||
* A ResponderID identifies the responder -- or more correctly, the
|
||||
* signer of the response. The ASN.1 definition of a ResponderID is:
|
||||
*
|
||||
* ResponderID ::= CHOICE {
|
||||
* byName [1] EXPLICIT Name,
|
||||
* byKey [2] EXPLICIT KeyHash }
|
||||
*
|
||||
* Because it is CHOICE, the type of identification used and the
|
||||
* identification itself are actually encoded together. To represent
|
||||
* this same information internally, we explicitly define a type and
|
||||
* save it, along with the value, into a data structure.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
ocspResponderID_other = -1, /* unknown kind of responderID */
|
||||
ocspResponderID_byName = 1,
|
||||
ocspResponderID_byKey = 2
|
||||
} CERTOCSPResponderIDType;
|
||||
|
||||
#endif /* _OCSPT_H_ */
|
||||
356
security/nss/lib/certhigh/ocspti.h
Normal file
356
security/nss/lib/certhigh/ocspti.h
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Private header defining OCSP types.
|
||||
*/
|
||||
|
||||
#ifndef _OCSPTI_H_
|
||||
#define _OCSPTI_H_
|
||||
|
||||
#include "ocspt.h"
|
||||
|
||||
#include "certt.h"
|
||||
#include "plarena.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
|
||||
/*
|
||||
* Some notes about naming conventions...
|
||||
*
|
||||
* The public data types all start with "CERTOCSP" (e.g. CERTOCSPRequest).
|
||||
* (Even the public types are opaque, however. Only their names are
|
||||
* "exported".)
|
||||
*
|
||||
* Internal-only data types drop the "CERT" prefix and use only the
|
||||
* lower-case "ocsp" (e.g. ocspTBSRequest), for brevity sake.
|
||||
*
|
||||
* In either case, the base/suffix of the type name usually matches the
|
||||
* name as defined in the OCSP specification. The exceptions to this are:
|
||||
* - When there is overlap between the "OCSP" or "ocsp" prefix and
|
||||
* the name used in the standard. That is, you cannot strip off the
|
||||
* "CERTOCSP" or "ocsp" prefix and necessarily get the name of the
|
||||
* type as it is defined in the standard; the "real" name will be
|
||||
* *either* "OCSPSuffix" or just "Suffix".
|
||||
* - When the name in the standard was a little too generic. (e.g. The
|
||||
* standard defines "Request" but we call it a "SingleRequest".)
|
||||
* In this case a comment above the type definition calls attention
|
||||
* to the difference.
|
||||
*
|
||||
* The definitions laid out in this header file are intended to follow
|
||||
* the same order as the definitions in the OCSP specification itself.
|
||||
* With the OCSP standard in hand, you should be able to move through
|
||||
* this file and follow along. To future modifiers of this file: please
|
||||
* try to keep it that way. The only exceptions are the few cases where
|
||||
* we need to define a type before it is referenced (e.g. enumerations),
|
||||
* whereas in the OCSP specification these are usually defined the other
|
||||
* way around (reference before definition).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Forward-declarations of internal-only data structures.
|
||||
*
|
||||
* These are in alphabetical order (case-insensitive); please keep it that way!
|
||||
*/
|
||||
typedef struct ocspBasicOCSPResponseStr ocspBasicOCSPResponse;
|
||||
typedef struct ocspCertStatusStr ocspCertStatus;
|
||||
typedef struct ocspResponderIDStr ocspResponderID;
|
||||
typedef struct ocspResponseBytesStr ocspResponseBytes;
|
||||
typedef struct ocspResponseDataStr ocspResponseData;
|
||||
typedef struct ocspRevokedInfoStr ocspRevokedInfo;
|
||||
typedef struct ocspServiceLocatorStr ocspServiceLocator;
|
||||
typedef struct ocspSignatureStr ocspSignature;
|
||||
typedef struct ocspSingleRequestStr ocspSingleRequest;
|
||||
typedef struct ocspSingleResponseStr ocspSingleResponse;
|
||||
typedef struct ocspTBSRequestStr ocspTBSRequest;
|
||||
|
||||
/*
|
||||
* An OCSPRequest; this is what is sent (encoded) to an OCSP responder.
|
||||
*/
|
||||
struct CERTOCSPRequestStr {
|
||||
PLArenaPool *arena; /* local; not part of encoding */
|
||||
ocspTBSRequest *tbsRequest;
|
||||
ocspSignature *optionalSignature;
|
||||
};
|
||||
|
||||
/*
|
||||
* A TBSRequest; when an OCSPRequest is signed, the encoding of this
|
||||
* is what the signature is actually applied to. ("TBS" == To Be Signed)
|
||||
* Whether signed or not, however, this structure will be present, and
|
||||
* is the "meat" of the OCSPRequest.
|
||||
*
|
||||
* Note that the "requestorName" field cannot be encoded/decoded in the
|
||||
* same pass as the entire request -- it needs to be handled with a special
|
||||
* call to convert to/from our internal form of a GeneralName. Thus the
|
||||
* "derRequestorName" field, which is the actual DER-encoded bytes.
|
||||
*
|
||||
* The "extensionHandle" field is used on creation only; it holds
|
||||
* in-progress extensions as they are optionally added to the request.
|
||||
*/
|
||||
struct ocspTBSRequestStr {
|
||||
SECItem version; /* an INTEGER */
|
||||
SECItem *derRequestorName; /* encoded GeneralName; see above */
|
||||
CERTGeneralNameList *requestorName; /* local; not part of encoding */
|
||||
ocspSingleRequest **requestList;
|
||||
CERTCertExtension **requestExtensions;
|
||||
void *extensionHandle; /* local; not part of encoding */
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the actual signature information for an OCSPRequest (applied to
|
||||
* the TBSRequest structure) or for a BasicOCSPResponse (applied to a
|
||||
* ResponseData structure).
|
||||
*
|
||||
* Note that the "signature" field itself is a BIT STRING; operations on
|
||||
* it need to keep that in mind, converting the length to bytes as needed
|
||||
* and back again afterward (so that the length is usually expressing bits).
|
||||
*
|
||||
* The "cert" field is the signer's certificate. In the case of a received
|
||||
* signature, it will be filled in when the signature is verified. In the
|
||||
* case of a created signature, it is filled in on creation and will be the
|
||||
* cert used to create the signature when the signing-and-encoding occurs,
|
||||
* as well as the cert (and its chain) to fill in derCerts if requested.
|
||||
*
|
||||
* The extra fields cache information about the signature after we have
|
||||
* attempted a verification. "wasChecked", if true, means the signature
|
||||
* has been checked against the appropriate data and thus that "status"
|
||||
* contains the result of that verification. If "status" is not SECSuccess,
|
||||
* "failureReason" is a copy of the error code that was set at the time;
|
||||
* presumably it tells why the signature verification failed.
|
||||
*/
|
||||
struct ocspSignatureStr {
|
||||
SECAlgorithmID signatureAlgorithm;
|
||||
SECItem signature; /* a BIT STRING */
|
||||
SECItem **derCerts; /* a SEQUENCE OF Certificate */
|
||||
CERTCertificate *cert; /* local; not part of encoding */
|
||||
PRBool wasChecked; /* local; not part of encoding */
|
||||
SECStatus status; /* local; not part of encoding */
|
||||
int failureReason; /* local; not part of encoding */
|
||||
};
|
||||
|
||||
/*
|
||||
* An OCSPRequest contains a SEQUENCE OF these, one for each certificate
|
||||
* whose status is being checked.
|
||||
*
|
||||
* Note that in the OCSP specification this is just called "Request",
|
||||
* but since that seemed confusing (vs. an OCSPRequest) and to be more
|
||||
* consistent with the parallel type "SingleResponse", I called it a
|
||||
* "SingleRequest".
|
||||
*
|
||||
* XXX figure out how to get rid of that arena -- there must be a way
|
||||
*/
|
||||
struct ocspSingleRequestStr {
|
||||
PLArenaPool *arena; /* just a copy of the response arena,
|
||||
* needed here for extension handling
|
||||
* routines, on creation only */
|
||||
CERTOCSPCertID *reqCert;
|
||||
CERTCertExtension **singleRequestExtensions;
|
||||
};
|
||||
|
||||
/*
|
||||
* A CertID is the means of identifying a certificate, used both in requests
|
||||
* and in responses.
|
||||
*
|
||||
* When in a SingleRequest it specifies the certificate to be checked.
|
||||
* When in a SingleResponse it is the cert whose status is being given.
|
||||
*/
|
||||
struct CERTOCSPCertIDStr {
|
||||
SECAlgorithmID hashAlgorithm;
|
||||
SECItem issuerNameHash; /* an OCTET STRING */
|
||||
SECItem issuerKeyHash; /* an OCTET STRING */
|
||||
SECItem serialNumber; /* an INTEGER */
|
||||
SECItem issuerSHA1NameHash; /* keep other hashes around when */
|
||||
SECItem issuerMD5NameHash; /* we have them */
|
||||
SECItem issuerMD2NameHash;
|
||||
SECItem issuerSHA1KeyHash; /* keep other hashes around when */
|
||||
SECItem issuerMD5KeyHash; /* we have them */
|
||||
SECItem issuerMD2KeyHash;
|
||||
PLArenaPool *poolp;
|
||||
};
|
||||
|
||||
/*
|
||||
* This describes the value of the responseStatus field in an OCSPResponse.
|
||||
* The corresponding ASN.1 definition is:
|
||||
*
|
||||
* OCSPResponseStatus ::= ENUMERATED {
|
||||
* successful (0), --Response has valid confirmations
|
||||
* malformedRequest (1), --Illegal confirmation request
|
||||
* internalError (2), --Internal error in issuer
|
||||
* tryLater (3), --Try again later
|
||||
* --(4) is not used
|
||||
* sigRequired (5), --Must sign the request
|
||||
* unauthorized (6), --Request unauthorized
|
||||
* }
|
||||
*/
|
||||
typedef enum {
|
||||
ocspResponse_min = 0,
|
||||
ocspResponse_successful = 0,
|
||||
ocspResponse_malformedRequest = 1,
|
||||
ocspResponse_internalError = 2,
|
||||
ocspResponse_tryLater = 3,
|
||||
ocspResponse_unused = 4,
|
||||
ocspResponse_sigRequired = 5,
|
||||
ocspResponse_unauthorized = 6,
|
||||
ocspResponse_max = 6 /* Please update max when adding values.
|
||||
* Remember to also update arrays, e.g.
|
||||
* "responseStatusNames" in ocspclnt.c
|
||||
* and potentially other places. */
|
||||
} ocspResponseStatus;
|
||||
|
||||
/*
|
||||
* An OCSPResponse is what is sent (encoded) by an OCSP responder.
|
||||
*
|
||||
* The field "responseStatus" is the ASN.1 encoded value; the field
|
||||
* "statusValue" is simply that same value translated into our local
|
||||
* type ocspResponseStatus.
|
||||
*/
|
||||
struct CERTOCSPResponseStr {
|
||||
PLArenaPool *arena; /* local; not part of encoding */
|
||||
SECItem responseStatus; /* an ENUMERATED, see above */
|
||||
ocspResponseStatus statusValue; /* local; not part of encoding */
|
||||
ocspResponseBytes *responseBytes; /* only when status is successful */
|
||||
};
|
||||
|
||||
/*
|
||||
* A ResponseBytes (despite appearances) is what contains the meat
|
||||
* of a successful response -- but still in encoded form. The type
|
||||
* given as "responseType" tells you how to decode the string.
|
||||
*
|
||||
* We look at the OID and translate it into our local OID representation
|
||||
* "responseTypeTag", and use that value to tell us how to decode the
|
||||
* actual response itself. For now the only kind of OCSP response we
|
||||
* know about is a BasicOCSPResponse. However, the intention in the
|
||||
* OCSP specification is to allow for other response types, so we are
|
||||
* building in that flexibility from the start and thus put a pointer
|
||||
* to that data structure inside of a union. Whenever OCSP adds more
|
||||
* response types, just add them to the union.
|
||||
*/
|
||||
struct ocspResponseBytesStr {
|
||||
SECItem responseType; /* an OBJECT IDENTIFIER */
|
||||
SECOidTag responseTypeTag; /* local; not part of encoding */
|
||||
SECItem response; /* an OCTET STRING */
|
||||
union {
|
||||
ocspBasicOCSPResponse *basic; /* when type is id-pkix-ocsp-basic */
|
||||
} decodedResponse; /* local; not part of encoding */
|
||||
};
|
||||
|
||||
/*
|
||||
* A BasicOCSPResponse -- when the responseType in a ResponseBytes is
|
||||
* id-pkix-ocsp-basic, the "response" OCTET STRING above is the DER
|
||||
* encoding of one of these.
|
||||
*
|
||||
* Note that in the OCSP specification, the signature fields are not
|
||||
* part of a separate sub-structure. But since they are the same fields
|
||||
* as we define for the signature in a request, it made sense to share
|
||||
* the C data structure here and in some shared code to operate on them.
|
||||
*/
|
||||
struct ocspBasicOCSPResponseStr {
|
||||
SECItem tbsResponseDataDER;
|
||||
ocspResponseData *tbsResponseData; /* "tbs" == To Be Signed */
|
||||
ocspSignature responseSignature;
|
||||
};
|
||||
|
||||
/*
|
||||
* A ResponseData is the part of a BasicOCSPResponse that is signed
|
||||
* (after it is DER encoded). It contains the real details of the response
|
||||
* (a per-certificate status).
|
||||
*/
|
||||
struct ocspResponseDataStr {
|
||||
SECItem version; /* an INTEGER */
|
||||
SECItem derResponderID;
|
||||
ocspResponderID *responderID; /* local; not part of encoding */
|
||||
SECItem producedAt; /* a GeneralizedTime */
|
||||
CERTOCSPSingleResponse **responses;
|
||||
CERTCertExtension **responseExtensions;
|
||||
};
|
||||
|
||||
struct ocspResponderIDStr {
|
||||
CERTOCSPResponderIDType responderIDType; /* local; not part of encoding */
|
||||
union {
|
||||
CERTName name; /* when ocspResponderID_byName */
|
||||
SECItem keyHash; /* when ocspResponderID_byKey */
|
||||
SECItem other; /* when ocspResponderID_other */
|
||||
} responderIDValue;
|
||||
};
|
||||
|
||||
/*
|
||||
* The ResponseData in a BasicOCSPResponse contains a SEQUENCE OF
|
||||
* SingleResponse -- one for each certificate whose status is being supplied.
|
||||
*
|
||||
* XXX figure out how to get rid of that arena -- there must be a way
|
||||
*/
|
||||
struct CERTOCSPSingleResponseStr {
|
||||
PLArenaPool *arena; /* just a copy of the response arena,
|
||||
* needed here for extension handling
|
||||
* routines, on creation only */
|
||||
CERTOCSPCertID *certID;
|
||||
SECItem derCertStatus;
|
||||
ocspCertStatus *certStatus; /* local; not part of encoding */
|
||||
SECItem thisUpdate; /* a GeneralizedTime */
|
||||
SECItem *nextUpdate; /* a GeneralizedTime */
|
||||
CERTCertExtension **singleExtensions;
|
||||
};
|
||||
|
||||
/*
|
||||
* A CertStatus is the actual per-certificate status. Its ASN.1 definition:
|
||||
*
|
||||
* CertStatus ::= CHOICE {
|
||||
* good [0] IMPLICIT NULL,
|
||||
* revoked [1] IMPLICIT RevokedInfo,
|
||||
* unknown [2] IMPLICIT UnknownInfo }
|
||||
*
|
||||
* (where for now UnknownInfo is defined to be NULL but in the
|
||||
* future may be replaced with an enumeration).
|
||||
*
|
||||
* Because it is CHOICE, the status value and its associated information
|
||||
* (if any) are actually encoded together. To represent this same
|
||||
* information internally, we explicitly define a type and save it,
|
||||
* along with the value, into a data structure.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
ocspCertStatus_good, /* cert is not revoked */
|
||||
ocspCertStatus_revoked, /* cert is revoked */
|
||||
ocspCertStatus_unknown, /* cert was unknown to the responder */
|
||||
ocspCertStatus_other /* status was not an expected value */
|
||||
} ocspCertStatusType;
|
||||
|
||||
/*
|
||||
* This is the actual per-certificate status.
|
||||
*
|
||||
* The "goodInfo" and "unknownInfo" items are only place-holders for a NULL.
|
||||
* (Though someday OCSP may replace UnknownInfo with an enumeration that
|
||||
* gives more detailed information.)
|
||||
*/
|
||||
struct ocspCertStatusStr {
|
||||
ocspCertStatusType certStatusType; /* local; not part of encoding */
|
||||
union {
|
||||
SECItem *goodInfo; /* when ocspCertStatus_good */
|
||||
ocspRevokedInfo *revokedInfo; /* when ocspCertStatus_revoked */
|
||||
SECItem *unknownInfo; /* when ocspCertStatus_unknown */
|
||||
SECItem *otherInfo; /* when ocspCertStatus_other */
|
||||
} certStatusInfo;
|
||||
};
|
||||
|
||||
/*
|
||||
* A RevokedInfo gives information about a revoked certificate -- when it
|
||||
* was revoked and why.
|
||||
*/
|
||||
struct ocspRevokedInfoStr {
|
||||
SECItem revocationTime; /* a GeneralizedTime */
|
||||
SECItem *revocationReason; /* a CRLReason; ignored for now */
|
||||
};
|
||||
|
||||
/*
|
||||
* ServiceLocator can be included as one of the singleRequestExtensions.
|
||||
* When added, it specifies the (name of the) issuer of the cert being
|
||||
* checked, and optionally the value of the AuthorityInfoAccess extension
|
||||
* if the cert has one.
|
||||
*/
|
||||
struct ocspServiceLocatorStr {
|
||||
CERTName *issuer;
|
||||
SECItem locator; /* DER encoded authInfoAccess extension from cert */
|
||||
};
|
||||
|
||||
#endif /* _OCSPTI_H_ */
|
||||
212
security/nss/lib/certhigh/xcrldist.c
Normal file
212
security/nss/lib/certhigh/xcrldist.c
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Code for dealing with x.509 v3 CRL Distribution Point extension.
|
||||
*/
|
||||
#include "genname.h"
|
||||
#include "certt.h"
|
||||
#include "secerr.h"
|
||||
|
||||
SEC_ASN1_MKSUB(SEC_AnyTemplate)
|
||||
SEC_ASN1_MKSUB(SEC_BitStringTemplate)
|
||||
|
||||
extern void PrepareBitStringForEncoding(SECItem *bitMap, SECItem *value);
|
||||
|
||||
static const SEC_ASN1Template FullNameTemplate[] = {
|
||||
{ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0,
|
||||
offsetof(CRLDistributionPoint, derFullName),
|
||||
CERT_GeneralNamesTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template RelativeNameTemplate[] = {
|
||||
{ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1,
|
||||
offsetof(CRLDistributionPoint, distPoint.relativeName),
|
||||
CERT_RDNTemplate }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template DistributionPointNameTemplate[] = {
|
||||
{ SEC_ASN1_CHOICE,
|
||||
offsetof(CRLDistributionPoint, distPointType), NULL,
|
||||
sizeof(CRLDistributionPoint) },
|
||||
{ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0,
|
||||
offsetof(CRLDistributionPoint, derFullName),
|
||||
CERT_GeneralNamesTemplate, generalName },
|
||||
{ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1,
|
||||
offsetof(CRLDistributionPoint, distPoint.relativeName),
|
||||
CERT_RDNTemplate, relativeDistinguishedName },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template CRLDistributionPointTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CRLDistributionPoint) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC |
|
||||
SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 0,
|
||||
offsetof(CRLDistributionPoint, derDistPoint),
|
||||
SEC_ASN1_SUB(SEC_AnyTemplate) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
|
||||
offsetof(CRLDistributionPoint, bitsmap),
|
||||
SEC_ASN1_SUB(SEC_BitStringTemplate) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC |
|
||||
SEC_ASN1_CONSTRUCTED | 2,
|
||||
offsetof(CRLDistributionPoint, derCrlIssuer),
|
||||
CERT_GeneralNamesTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERTCRLDistributionPointsTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF, 0, CRLDistributionPointTemplate }
|
||||
};
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeCRLDistributionPoints(PLArenaPool *arena,
|
||||
CERTCrlDistributionPoints *value,
|
||||
SECItem *derValue)
|
||||
{
|
||||
CRLDistributionPoint **pointList, *point;
|
||||
PLArenaPool *ourPool = NULL;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Assert(derValue);
|
||||
PORT_Assert(value && value->distPoints);
|
||||
|
||||
do {
|
||||
ourPool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
|
||||
if (ourPool == NULL) {
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
pointList = value->distPoints;
|
||||
while (*pointList) {
|
||||
point = *pointList;
|
||||
point->derFullName = NULL;
|
||||
point->derDistPoint.data = NULL;
|
||||
|
||||
switch (point->distPointType) {
|
||||
case generalName:
|
||||
point->derFullName = cert_EncodeGeneralNames(ourPool, point->distPoint.fullName);
|
||||
|
||||
if (!point->derFullName ||
|
||||
!SEC_ASN1EncodeItem(ourPool, &point->derDistPoint,
|
||||
point, FullNameTemplate))
|
||||
rv = SECFailure;
|
||||
break;
|
||||
|
||||
case relativeDistinguishedName:
|
||||
if (!SEC_ASN1EncodeItem(ourPool, &point->derDistPoint,
|
||||
point, RelativeNameTemplate))
|
||||
rv = SECFailure;
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
|
||||
if (point->reasons.data)
|
||||
PrepareBitStringForEncoding(&point->bitsmap, &point->reasons);
|
||||
|
||||
if (point->crlIssuer) {
|
||||
point->derCrlIssuer = cert_EncodeGeneralNames(ourPool, point->crlIssuer);
|
||||
if (!point->derCrlIssuer) {
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++pointList;
|
||||
}
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
if (!SEC_ASN1EncodeItem(arena, derValue, value,
|
||||
CERTCRLDistributionPointsTemplate)) {
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
PORT_FreeArena(ourPool, PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
CERTCrlDistributionPoints *
|
||||
CERT_DecodeCRLDistributionPoints(PLArenaPool *arena, SECItem *encodedValue)
|
||||
{
|
||||
CERTCrlDistributionPoints *value = NULL;
|
||||
CRLDistributionPoint **pointList, *point;
|
||||
SECStatus rv = SECSuccess;
|
||||
SECItem newEncodedValue;
|
||||
|
||||
PORT_Assert(arena);
|
||||
do {
|
||||
value = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
|
||||
if (value == NULL) {
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
/* copy the DER into the arena, since Quick DER returns data that points
|
||||
into the DER input, which may get freed by the caller */
|
||||
rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
|
||||
rv = SEC_QuickDERDecodeItem(arena, &value->distPoints,
|
||||
CERTCRLDistributionPointsTemplate, &newEncodedValue);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
|
||||
pointList = value->distPoints;
|
||||
while (NULL != (point = *pointList)) {
|
||||
|
||||
/* get the data if the distributionPointName is not omitted */
|
||||
if (point->derDistPoint.data != NULL) {
|
||||
rv = SEC_QuickDERDecodeItem(arena, point,
|
||||
DistributionPointNameTemplate, &(point->derDistPoint));
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
|
||||
switch (point->distPointType) {
|
||||
case generalName:
|
||||
point->distPoint.fullName =
|
||||
cert_DecodeGeneralNames(arena, point->derFullName);
|
||||
rv = point->distPoint.fullName ? SECSuccess : SECFailure;
|
||||
break;
|
||||
|
||||
case relativeDistinguishedName:
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
|
||||
rv = SECFailure;
|
||||
break;
|
||||
} /* end switch */
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
} /* end if */
|
||||
|
||||
/* Get the reason code if it's not omitted in the encoding */
|
||||
if (point->bitsmap.data != NULL) {
|
||||
SECItem bitsmap = point->bitsmap;
|
||||
DER_ConvertBitString(&bitsmap);
|
||||
rv = SECITEM_CopyItem(arena, &point->reasons, &bitsmap);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the crl issuer name if it's not omitted in the encoding */
|
||||
if (point->derCrlIssuer != NULL) {
|
||||
point->crlIssuer = cert_DecodeGeneralNames(arena,
|
||||
point->derCrlIssuer);
|
||||
if (!point->crlIssuer)
|
||||
break;
|
||||
}
|
||||
++pointList;
|
||||
} /* end while points remain */
|
||||
} while (0);
|
||||
return (rv == SECSuccess ? value : NULL);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue