mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-16 04:20:32 +01:00
a572ea8ca3
bug1095307, bug1073330(backout), bug1084986, bug1050069, bug942172, bug1054547, bug532081, bug1096348, bug1058870, bug1093940, bug1102985, bug1112461, bug1094492, bug112029, bug1119983, bug1120685, bug1120691, bug1113632, bug863076, bug1082973, bug1124539, bug1117617, bug1117621, bug1121273, bug753136, bug921684, bug1132818, bug1125375, bug647690, bug1055441, bug1134455, bug975010, bug950369, bug1128367, bug1129573, bug1136095, bug1117897, bug1113453, bug1061725, bug1073330, bug1111901, bug1083900, bug1136095, bug1138820, bug1096741, bug1134548, bug345725, bug950348, bug950344, bug1151037, bug991783, bug1153994
230 lines
5.4 KiB
C
230 lines
5.4 KiB
C
/* 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 X509.V3 extensions.
|
|
*/
|
|
|
|
#include "cert.h"
|
|
#include "secitem.h"
|
|
#include "secoid.h"
|
|
#include "secder.h"
|
|
#include "secasn1.h"
|
|
#include "certxutl.h"
|
|
#include "secerr.h"
|
|
|
|
SECStatus
|
|
CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid,
|
|
SECItem *value)
|
|
{
|
|
return (cert_FindExtensionByOID (cert->extensions, oid, value));
|
|
}
|
|
|
|
|
|
SECStatus
|
|
CERT_FindCertExtension(const CERTCertificate *cert, int tag, SECItem *value)
|
|
{
|
|
return (cert_FindExtension (cert->extensions, tag, value));
|
|
}
|
|
|
|
static void
|
|
SetExts(void *object, CERTCertExtension **exts)
|
|
{
|
|
CERTCertificate *cert = (CERTCertificate *)object;
|
|
|
|
cert->extensions = exts;
|
|
DER_SetUInteger (cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3);
|
|
}
|
|
|
|
void *
|
|
CERT_StartCertExtensions(CERTCertificate *cert)
|
|
{
|
|
return (cert_StartExtensions ((void *)cert, cert->arena, SetExts));
|
|
}
|
|
|
|
/*
|
|
* get the value of the Netscape Certificate Type Extension
|
|
*/
|
|
SECStatus
|
|
CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem)
|
|
{
|
|
|
|
return (CERT_FindBitStringExtension
|
|
(cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem));
|
|
}
|
|
|
|
|
|
/*
|
|
* get the value of a string type extension
|
|
*/
|
|
char *
|
|
CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag)
|
|
{
|
|
SECItem wrapperItem, tmpItem = {siBuffer,0};
|
|
SECStatus rv;
|
|
PLArenaPool *arena = NULL;
|
|
char *retstring = NULL;
|
|
|
|
wrapperItem.data = NULL;
|
|
tmpItem.data = NULL;
|
|
|
|
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
|
|
if ( ! arena ) {
|
|
goto loser;
|
|
}
|
|
|
|
rv = cert_FindExtension(cert->extensions, oidtag,
|
|
&wrapperItem);
|
|
if ( rv != SECSuccess ) {
|
|
goto loser;
|
|
}
|
|
|
|
rv = SEC_QuickDERDecodeItem(arena, &tmpItem,
|
|
SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem);
|
|
|
|
if ( rv != SECSuccess ) {
|
|
goto loser;
|
|
}
|
|
|
|
retstring = (char *)PORT_Alloc(tmpItem.len + 1 );
|
|
if ( retstring == NULL ) {
|
|
goto loser;
|
|
}
|
|
|
|
PORT_Memcpy(retstring, tmpItem.data, tmpItem.len);
|
|
retstring[tmpItem.len] = '\0';
|
|
|
|
loser:
|
|
if ( arena ) {
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
}
|
|
|
|
if ( wrapperItem.data ) {
|
|
PORT_Free(wrapperItem.data);
|
|
}
|
|
|
|
return(retstring);
|
|
}
|
|
|
|
/*
|
|
* get the value of the X.509 v3 Key Usage Extension
|
|
*/
|
|
SECStatus
|
|
CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem)
|
|
{
|
|
|
|
return (CERT_FindBitStringExtension(cert->extensions,
|
|
SEC_OID_X509_KEY_USAGE, retItem));
|
|
}
|
|
|
|
/*
|
|
* get the value of the X.509 v3 Key Usage Extension
|
|
*/
|
|
SECStatus
|
|
CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem)
|
|
{
|
|
|
|
SECStatus rv;
|
|
SECItem encodedValue = {siBuffer, NULL, 0 };
|
|
SECItem decodedValue = {siBuffer, NULL, 0 };
|
|
|
|
rv = cert_FindExtension
|
|
(cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, &encodedValue);
|
|
if (rv == SECSuccess) {
|
|
PLArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
if (tmpArena) {
|
|
rv = SEC_QuickDERDecodeItem(tmpArena, &decodedValue,
|
|
SEC_ASN1_GET(SEC_OctetStringTemplate),
|
|
&encodedValue);
|
|
if (rv == SECSuccess) {
|
|
rv = SECITEM_CopyItem(NULL, retItem, &decodedValue);
|
|
}
|
|
PORT_FreeArena(tmpArena, PR_FALSE);
|
|
} else {
|
|
rv = SECFailure;
|
|
}
|
|
}
|
|
SECITEM_FreeItem(&encodedValue, PR_FALSE);
|
|
return rv;
|
|
}
|
|
|
|
SECStatus
|
|
CERT_FindBasicConstraintExten(CERTCertificate *cert,
|
|
CERTBasicConstraints *value)
|
|
{
|
|
SECItem encodedExtenValue;
|
|
SECStatus rv;
|
|
|
|
encodedExtenValue.data = NULL;
|
|
encodedExtenValue.len = 0;
|
|
|
|
rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS,
|
|
&encodedExtenValue);
|
|
if ( rv != SECSuccess ) {
|
|
return (rv);
|
|
}
|
|
|
|
rv = CERT_DecodeBasicConstraintValue (value, &encodedExtenValue);
|
|
|
|
/* free the raw extension data */
|
|
PORT_Free(encodedExtenValue.data);
|
|
encodedExtenValue.data = NULL;
|
|
|
|
return(rv);
|
|
}
|
|
|
|
CERTAuthKeyID *
|
|
CERT_FindAuthKeyIDExten (PLArenaPool *arena, CERTCertificate *cert)
|
|
{
|
|
SECItem encodedExtenValue;
|
|
SECStatus rv;
|
|
CERTAuthKeyID *ret;
|
|
|
|
encodedExtenValue.data = NULL;
|
|
encodedExtenValue.len = 0;
|
|
|
|
rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID,
|
|
&encodedExtenValue);
|
|
if ( rv != SECSuccess ) {
|
|
return (NULL);
|
|
}
|
|
|
|
ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
|
|
|
|
PORT_Free(encodedExtenValue.data);
|
|
encodedExtenValue.data = NULL;
|
|
|
|
return(ret);
|
|
}
|
|
|
|
SECStatus
|
|
CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage)
|
|
{
|
|
SECItem keyUsage;
|
|
SECStatus rv;
|
|
|
|
/* There is no extension, v1 or v2 certificate */
|
|
if (cert->extensions == NULL) {
|
|
return (SECSuccess);
|
|
}
|
|
|
|
keyUsage.data = NULL;
|
|
|
|
/* This code formerly ignored the Key Usage extension if it was
|
|
** marked non-critical. That was wrong. Since we do understand it,
|
|
** we are obligated to honor it, whether or not it is critical.
|
|
*/
|
|
rv = CERT_FindKeyUsageExtension(cert, &keyUsage);
|
|
if (rv == SECFailure) {
|
|
rv = (PORT_GetError () == SEC_ERROR_EXTENSION_NOT_FOUND) ?
|
|
SECSuccess : SECFailure;
|
|
} else if (!(keyUsage.data[0] & usage)) {
|
|
PORT_SetError (SEC_ERROR_CERT_USAGES_INVALID);
|
|
rv = SECFailure;
|
|
}
|
|
PORT_Free (keyUsage.data);
|
|
return (rv);
|
|
}
|