Save more decoded data from certificate for later use with X.509 functions.

This commit is contained in:
John Safranek 2013-11-19 14:44:55 -08:00
parent c0007ad6b3
commit 0fd6aed9b6
7 changed files with 439 additions and 7 deletions

View File

@ -1303,6 +1303,20 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
#ifdef OPENSSL_EXTRA
XMEMSET(&cert->issuerName, 0, sizeof(DecodedName));
XMEMSET(&cert->subjectName, 0, sizeof(DecodedName));
cert->extBasicConstSet = 0;
cert->extBasicConstCrit = 0;
cert->extBasicConstPlSet = 0;
cert->pathLength = 0;
cert->extSubjAltNameSet = 0;
cert->extSubjAltNameCrit = 0;
cert->extAuthKeyIdCrit = 0;
cert->extSubjKeyIdCrit = 0;
cert->extKeyUsageSet = 0;
cert->extKeyUsageCrit = 0;
cert->extKeyUsage = 0;
#ifdef HAVE_ECC
cert->pkCurveOID = 0;
#endif /* HAVE_ECC */
#endif /* OPENSSL_EXTRA */
#ifdef CYASSL_SEP
cert->deviceTypeSz = 0;
@ -1311,6 +1325,10 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
cert->hwType = NULL;
cert->hwSerialNumSz = 0;
cert->hwSerialNum = NULL;
#ifdef OPENSSL_EXTRA
cert->extCertPolicySet = 0;
cert->extCertPolicyCrit = 0;
#endif /* OPENSSL_EXTRA */
#endif /* CYASSL_SEP */
}
@ -1509,6 +1527,9 @@ static int GetKey(DecodedCert* cert)
oid += cert->source[cert->srcIdx++];
if (CheckCurve(oid) < 0)
return ECC_CURVE_OID_E;
#ifdef OPENSSL_EXTRA
cert->pkCurveOID = oid;
#endif /* OPENSSL_EXTRA */
/* key header */
b = cert->source[cert->srcIdx++];
@ -2882,8 +2903,28 @@ static void DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
return;
}
if (input[idx])
if (input[idx++])
cert->isCA = 1;
#ifdef OPENSSL_EXTRA
/* If there isn't any more data, return. */
if (idx >= (word32)sz)
return;
/* Anything left should be the optional pathlength */
if (input[idx++] != ASN_INTEGER) {
CYASSL_MSG("\tfail: pathlen not INTEGER");
return;
}
if (input[idx++] != 1) {
CYASSL_MSG("\tfail: pathlen too long");
return;
}
cert->pathLength = input[idx];
cert->extBasicConstPlSet = 1;
#endif /* OPENSSL_EXTRA */
}
@ -3045,7 +3086,6 @@ static void DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
ShaUpdate(&sha, input + idx, length);
ShaFinal(&sha, cert->extAuthKeyId);
}
cert->extAuthKeyIdSet = 1;
return;
}
@ -3077,12 +3117,44 @@ static void DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert)
ShaUpdate(&sha, input + idx, length);
ShaFinal(&sha, cert->extSubjKeyId);
}
cert->extSubjKeyIdSet = 1;
return;
}
#ifdef OPENSSL_EXTRA
static void DecodeKeyUsage(byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length;
byte unusedBits;
CYASSL_ENTER("DecodeKeyUsage");
if (input[idx++] != ASN_BIT_STRING) {
CYASSL_MSG("\tfail: key usage expected bit string");
return;
}
if (GetLength(input, &idx, &length, sz) < 0) {
CYASSL_MSG("\tfail: key usage bad length");
return;
}
unusedBits = input[idx++];
length--;
if (length == 2) {
cert->extKeyUsage = (input[idx] << 8) | input[idx+1];
cert->extKeyUsage >>= unusedBits;
}
else if (length == 1)
cert->extKeyUsage = (input[idx] << 1);
return;
}
#endif /* OPENSSL_EXTRA */
#ifdef CYASSL_SEP
static void DecodeCertPolicy(byte* input, int sz, DecodedCert* cert)
{
@ -3138,6 +3210,7 @@ static void DecodeCertExtensions(DecodedCert* cert)
byte* input = cert->extensions;
int length;
word32 oid;
byte critical;
CYASSL_ENTER("DecodeCertExtensions");
@ -3162,9 +3235,16 @@ static void DecodeCertExtensions(DecodedCert* cert)
}
/* check for critical flag */
critical = 0;
if (input[idx] == ASN_BOOLEAN) {
CYASSL_MSG("\tfound optional critical flag, moving past");
idx += (ASN_BOOL_SIZE + 1);
int boolLength = 0;
idx++;
if (GetLength(input, &idx, &boolLength, sz) < 0) {
CYASSL_MSG("\tfail: critical boolean length");
return;
}
if (input[idx++])
critical = 1;
}
/* process the extension based on the OID */
@ -3180,6 +3260,10 @@ static void DecodeCertExtensions(DecodedCert* cert)
switch (oid) {
case BASIC_CA_OID:
#ifdef OPENSSL_EXTRA
cert->extBasicConstSet = 1;
cert->extBasicConstCrit = critical;
#endif
DecodeBasicCaConstraint(&input[idx], length, cert);
break;
@ -3192,23 +3276,47 @@ static void DecodeCertExtensions(DecodedCert* cert)
break;
case ALT_NAMES_OID:
#ifdef OPENSSL_EXTRA
cert->extSubjAltNameSet = 1;
cert->extSubjAltNameCrit = critical;
#endif
DecodeAltNames(&input[idx], length, cert);
break;
case AUTH_KEY_OID:
cert->extAuthKeyIdSet = 1;
#ifdef OPENSSL_EXTRA
cert->extAuthKeyIdCrit = critical;
#endif
DecodeAuthKeyId(&input[idx], length, cert);
break;
case SUBJ_KEY_OID:
cert->extSubjKeyIdSet = 1;
#ifdef OPENSSL_EXTRA
cert->extSubjKeyIdCrit = critical;
#endif
DecodeSubjKeyId(&input[idx], length, cert);
break;
#ifdef CYASSL_SEP
case CERT_POLICY_OID:
#ifdef OPENSSL_EXTRA
cert->extCertPolicySet = 1;
cert->extCertPolicyCrit = critical;
#endif
DecodeCertPolicy(&input[idx], length, cert);
break;
#endif
#ifdef OPENSSL_EXTRA
case KEY_USAGE_OID:
cert->extKeyUsageSet = 1;
cert->extKeyUsageCrit = critical;
DecodeKeyUsage(&input[idx], length, cert);
break;
#endif
default:
CYASSL_MSG("\tExtension type not handled, skipping");
break;

View File

@ -199,7 +199,8 @@ enum Extensions_Sum {
CA_ISSUER_OID = 117,
AUTH_KEY_OID = 149,
SUBJ_KEY_OID = 128,
CERT_POLICY_OID = 146
CERT_POLICY_OID = 146,
KEY_USAGE_OID = 129 /* 2.5.29.15 */
};
enum CertificatePolicy_Sum {
@ -217,6 +218,18 @@ enum VerifyType {
};
/* Key usage extension bits */
#define KEYUSE_DIGITAL_SIG 0x0100
#define KEYUSE_CONTENT_COMMIT 0x0080
#define KEYUSE_KEY_ENCIPHER 0x0040
#define KEYUSE_DATA_ENCIPHER 0x0020
#define KEYUSE_KEY_AGREE 0x0010
#define KEYUSE_KEY_CERT_SIGN 0x0008
#define KEYUSE_CRL_SIGN 0x0004
#define KEYUSE_ENCIPHER_ONLY 0x0002
#define KEYUSE_DECIPHER_ONLY 0x0001
typedef struct DNS_entry DNS_entry;
struct DNS_entry {
@ -297,7 +310,23 @@ struct DecodedCert {
byte extSubjKeyIdSet; /* Set when the SKID was read from cert */
byte extAuthKeyId[SHA_SIZE]; /* Authority Key ID */
byte extAuthKeyIdSet; /* Set when the AKID was read from cert */
byte isCA; /* CA basic constraint true */
byte isCA; /* CA basic constraint true */
#ifdef OPENSSL_EXTRA
byte extBasicConstSet;
byte extBasicConstCrit;
byte extBasicConstPlSet;
word32 pathLength; /* CA basic constraint path length, opt */
byte extSubjAltNameSet;
byte extSubjAltNameCrit;
byte extAuthKeyIdCrit;
byte extSubjKeyIdCrit;
byte extKeyUsageSet;
byte extKeyUsageCrit;
word16 extKeyUsage; /* Key usage bitfield */
#ifdef HAVE_ECC
word32 pkCurveOID; /* Public Key's curve OID */
#endif /* HAVE_ECC */
#endif
byte* beforeDate;
int beforeDateLen;
byte* afterDate;
@ -330,6 +359,10 @@ struct DecodedCert {
byte* hwType;
int hwSerialNumSz;
byte* hwSerialNum;
#ifdef OPENSSL_EXTRA
byte extCertPolicySet;
byte extCertPolicyCrit;
#endif /* OPENSSL_EXTRA */
#endif /* CYASSL_SEP */
};

View File

@ -78,6 +78,9 @@
/* Uncomment next line if using Comverge settings */
/* #define COMVERGE */
/* Uncomment next line if using QL SEP settings */
/* #define CYASSL_QL */
#include <cyassl/ctaocrypt/visibility.h>
@ -524,6 +527,37 @@
#endif /* MICRIUM */
#ifdef CYASSL_QL
#ifndef CYASSL_SEP
#define CYASSL_SEP
#endif
#ifndef OPENSSL_EXTRA
#define OPENSSL_EXTRA
#endif
#ifndef SESSION_CERTS
#define SESSION_CERTS
#endif
#ifndef HAVE_AESCCM
#define HAVE_AESCCM
#endif
#ifndef ATOMIC_USER
#define ATOMIC_USER
#endif
#ifndef CYASSL_DER_LOAD
#define CYASSL_DER_LOAD
#endif
#ifndef KEEP_PEER_CERT
#define KEEP_PEER_CERT
#endif
#ifndef HAVE_ECC
#define HAVE_ECC
#endif
#ifndef SESSION_INDEX
#define SESSION_INDEX
#endif
#endif /* CYASSL_QL */
#if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \
!defined(CYASSL_LEANPSK) && !defined(NO_CYASSL_MEMORY)
#define USE_CYASSL_MEMORY

View File

@ -1661,6 +1661,10 @@ struct CYASSL_X509 {
byte hwType[EXTERNAL_SERIAL_SIZE];
int hwSerialNumSz;
byte hwSerialNum[EXTERNAL_SERIAL_SIZE];
#ifdef OPENSSL_EXTRA
byte certPolicySet;
byte certPolicyCrit;
#endif /* OPENSSL_EXTRA */
#endif
int notBeforeSz;
byte notBefore[MAX_DATE_SZ];
@ -1670,10 +1674,31 @@ struct CYASSL_X509 {
buffer sig;
int pubKeyOID;
buffer pubKey;
#ifdef HAVE_ECC
word32 pkCurveOID;
#endif /* HAVE_ECC */
buffer derCert; /* may need */
DNS_entry* altNames; /* alt names list */
DNS_entry* altNamesNext; /* hint for retrieval */
byte dynamicMemory; /* dynamic memory flag */
byte isCa;
#ifdef OPENSSL_EXTRA
word32 pathLength;
word16 keyUsage;
byte basicConstSet;
byte basicConstCrit;
byte basicConstPlSet;
byte subjAltNameSet;
byte subjAltNameCrit;
byte authKeyIdSet;
byte authKeyIdCrit;
byte authKeyId[SHA_SIZE];
byte subjKeyIdSet;
byte subjKeyIdCrit;
byte subjKeyId[SHA_SIZE];
byte keyUsageSet;
byte keyUsageCrit;
#endif /* OPENSSL_EXTRA */
};

View File

@ -99,6 +99,9 @@ typedef struct CYASSL_EVP_PKEY {
union {
char* ptr;
} pkey;
#ifdef HAVE_ECC
int pkey_curve;
#endif
} CYASSL_EVP_PKEY;
typedef struct CYASSL_MD4_CTX {
@ -413,6 +416,16 @@ CYASSL_API int CyaSSL_X509_STORE_CTX_get_error_depth(CYASSL_X509_STORE_CTX*);
CYASSL_API char* CyaSSL_X509_NAME_oneline(CYASSL_X509_NAME*, char*, int);
CYASSL_API CYASSL_X509_NAME* CyaSSL_X509_get_issuer_name(CYASSL_X509*);
CYASSL_API CYASSL_X509_NAME* CyaSSL_X509_get_subject_name(CYASSL_X509*);
CYASSL_API int CyaSSL_X509_ext_isSet_by_NID(CYASSL_X509*, int);
CYASSL_API int CyaSSL_X509_ext_get_critical_by_NID(CYASSL_X509*, int);
CYASSL_API int CyaSSL_X509_get_isCA(CYASSL_X509*);
CYASSL_API int CyaSSL_X509_get_isSet_pathLength(CYASSL_X509*);
CYASSL_API unsigned int CyaSSL_X509_get_pathLength(CYASSL_X509*);
CYASSL_API unsigned int CyaSSL_X509_get_keyUsage(CYASSL_X509*);
CYASSL_API unsigned char* CyaSSL_X509_get_authorityKeyID(
CYASSL_X509*, unsigned char*, int*);
CYASSL_API unsigned char* CyaSSL_X509_get_subjectKeyID(
CYASSL_X509*, unsigned char*, int*);
CYASSL_API int CyaSSL_X509_NAME_entry_count(CYASSL_X509_NAME*);
CYASSL_API int CyaSSL_X509_NAME_get_text_by_NID(
CYASSL_X509_NAME*, int, char*, int);

View File

@ -1271,6 +1271,31 @@ void InitX509(CYASSL_X509* x509, int dynamicFlag)
x509->altNames = NULL;
x509->altNamesNext = NULL;
x509->dynamicMemory = (byte)dynamicFlag;
x509->isCa = 0;
#ifdef OPENSSL_EXTRA
x509->pathLength = 0;
x509->basicConstSet = 0;
x509->basicConstCrit = 0;
x509->basicConstPlSet = 0;
x509->subjAltNameSet = 0;
x509->subjAltNameCrit = 0;
x509->authKeyIdSet = 0;
x509->authKeyIdCrit = 0;
XMEMSET(x509->authKeyId, 0, SHA_SIZE);
x509->subjKeyIdSet = 0;
x509->subjKeyIdCrit = 0;
XMEMSET(x509->subjKeyId, 0, SHA_SIZE);
x509->keyUsageSet = 0;
x509->keyUsageCrit = 0;
x509->keyUsage = 0;
#ifdef HAVE_ECC
x509->pkCurveOID = 0;
#endif /* HAVE_ECC */
#ifdef CYASSL_SEP
x509->certPolicySet = 0;
x509->certPolicyCrit = 0;
#endif /* CYASSL_SEP */
#endif /* OPENSSL_EXTRA */
}
@ -3156,6 +3181,33 @@ int CopyDecodedToX509(CYASSL_X509* x509, DecodedCert* dCert)
dCert->altNames = NULL; /* takes ownership */
x509->altNamesNext = x509->altNames; /* index hint */
x509->isCa = dCert->isCA;
#ifdef OPENSSL_EXTRA
x509->pathLength = dCert->pathLength;
x509->keyUsage = dCert->extKeyUsage;
x509->basicConstSet = dCert->extBasicConstSet;
x509->basicConstCrit = dCert->extBasicConstCrit;
x509->basicConstPlSet = dCert->extBasicConstPlSet;
x509->subjAltNameSet = dCert->extSubjAltNameSet;
x509->subjAltNameCrit = dCert->extSubjAltNameCrit;
x509->authKeyIdSet = dCert->extAuthKeyIdSet;
x509->authKeyIdCrit = dCert->extAuthKeyIdCrit;
XMEMCPY(x509->authKeyId, dCert->extAuthKeyId, SHA_SIZE);
x509->subjKeyIdSet = dCert->extSubjKeyIdSet;
x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit;
XMEMCPY(x509->subjKeyId, dCert->extSubjKeyId, SHA_SIZE);
x509->keyUsageSet = dCert->extKeyUsageSet;
x509->keyUsageCrit = dCert->extKeyUsageCrit;
#ifdef HAVE_ECC
x509->pkCurveOID = dCert->pkCurveOID;
#endif /* HAVE_ECC */
#ifdef CYASSL_SEP
x509->certPolicySet = dCert->extCertPolicySet;
x509->certPolicyCrit = dCert->extCertPolicyCrit;
#endif /* CYASSL_SEP */
#endif /* OPENSSL_EXTRA */
return ret;
}

167
src/ssl.c
View File

@ -7092,6 +7092,170 @@ int CyaSSL_set_compression(CYASSL* ssl)
}
#ifdef OPENSSL_EXTRA
int CyaSSL_X509_ext_isSet_by_NID(CYASSL_X509* x509, int nid)
{
int isSet = 0;
CYASSL_ENTER("CyaSSL_X509_ext_isSet_by_NID");
if (x509 != NULL) {
switch (nid) {
case BASIC_CA_OID: isSet = x509->basicConstSet; break;
case ALT_NAMES_OID: isSet = x509->subjAltNameSet; break;
case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break;
case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break;
case KEY_USAGE_OID: isSet = x509->keyUsageSet; break;
#ifdef CYASSL_SEP
case CERT_POLICY_OID: isSet = x509->certPolicySet; break;
#endif /* CYASSL_SEP */
}
}
CYASSL_LEAVE("CyaSSL_X509_ext_isSet_by_NID", isSet);
return isSet;
}
int CyaSSL_X509_ext_get_critical_by_NID(CYASSL_X509* x509, int nid)
{
int crit = 0;
CYASSL_ENTER("CyaSSL_X509_ext_get_critical_by_NID");
if (x509 != NULL) {
switch (nid) {
case BASIC_CA_OID: crit = x509->basicConstCrit; break;
case ALT_NAMES_OID: crit = x509->subjAltNameCrit; break;
case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break;
case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break;
case KEY_USAGE_OID: crit = x509->keyUsageCrit; break;
#ifdef CYASSL_SEP
case CERT_POLICY_OID: crit = x509->certPolicyCrit; break;
#endif /* CYASSL_SEP */
}
}
CYASSL_LEAVE("CyaSSL_X509_ext_get_critical_by_NID", crit);
return crit;
}
#endif
int CyaSSL_X509_get_isCA(CYASSL_X509* x509)
{
int isCA = 0;
CYASSL_ENTER("CyaSSL_X509_get_isCA");
if (x509 != NULL)
isCA = x509->isCa;
CYASSL_LEAVE("CyaSSL_X509_get_isCA", isCA);
return isCA;
}
#ifdef OPENSSL_EXTRA
int CyaSSL_X509_get_isSet_pathLength(CYASSL_X509* x509)
{
int isSet = 0;
CYASSL_ENTER("CyaSSL_X509_get_isSet_pathLength");
if (x509 != NULL)
isSet = x509->basicConstPlSet;
CYASSL_LEAVE("CyaSSL_X509_get_isSet_pathLength", isSet);
return isSet;
}
word32 CyaSSL_X509_get_pathLength(CYASSL_X509* x509)
{
word32 pathLength = 0;
CYASSL_ENTER("CyaSSL_X509_get_pathLength");
if (x509 != NULL)
pathLength = x509->pathLength;
CYASSL_LEAVE("CyaSSL_X509_get_pathLength", pathLength);
return pathLength;
}
unsigned int CyaSSL_X509_get_keyUsage(CYASSL_X509* x509)
{
word16 usage = 0;
CYASSL_ENTER("CyaSSL_X509_get_keyUsage");
if (x509 != NULL)
usage = x509->keyUsage;
CYASSL_LEAVE("CyaSSL_X509_get_keyUsage", usage);
return usage;
}
byte* CyaSSL_X509_get_authorityKeyID(
CYASSL_X509* x509, byte* dst, int* dstLen)
{
byte *id = NULL;
int copySz = min(dstLen != NULL ? *dstLen : 0, SHA_SIZE);
CYASSL_ENTER("CyaSSL_X509_get_authorityKeyID");
if (x509 != NULL) {
if (x509->authKeyIdSet)
id = x509->authKeyId;
if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
XMEMCPY(dst, id, copySz);
id = dst;
*dstLen = copySz;
}
}
CYASSL_LEAVE("CyaSSL_X509_get_authorityKeyID", copySz);
return id;
}
byte* CyaSSL_X509_get_subjectKeyID(
CYASSL_X509* x509, byte* dst, int* dstLen)
{
byte *id = NULL;
int copySz = min(dstLen != NULL ? *dstLen : 0, SHA_SIZE);
CYASSL_ENTER("CyaSSL_X509_get_subjectKeyID");
if (x509 != NULL) {
if (x509->subjKeyIdSet)
id = x509->subjKeyId;
if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
XMEMCPY(dst, id, copySz);
id = dst;
*dstLen = copySz;
}
}
CYASSL_LEAVE("CyaSSL_X509_get_subjectKeyID", copySz);
return id;
}
#endif
/* copy name into in buffer, at most sz bytes, if buffer is null will
malloc buffer, call responsible for freeing */
char* CyaSSL_X509_NAME_oneline(CYASSL_X509_NAME* name, char* in, int sz)
@ -8373,6 +8537,9 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format)
XMEMCPY(key->pkey.ptr,
x509->pubKey.buffer, x509->pubKey.length);
key->pkey_sz = x509->pubKey.length;
#ifdef HAVE_ECC
key->pkey_curve = (int)x509->pkCurveOID;
#endif /* HAVE_ECC */
}
}
return key;