added x509_build_generalNames() and x509_build_subjectAltNames() functions
This commit is contained in:
+121
-27
@@ -116,7 +116,7 @@ struct private_x509_t {
|
|||||||
/**
|
/**
|
||||||
* Signature algorithm
|
* Signature algorithm
|
||||||
*/
|
*/
|
||||||
int sigAlg;
|
int signatureAlgorithm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID representing the certificate issuer
|
* ID representing the certificate issuer
|
||||||
@@ -198,11 +198,6 @@ struct private_x509_t {
|
|||||||
*/
|
*/
|
||||||
bool isOcspSigner;
|
bool isOcspSigner;
|
||||||
|
|
||||||
/**
|
|
||||||
* Signature algorithm (must be identical to sigAlg)
|
|
||||||
*/
|
|
||||||
int algorithm;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature
|
* Signature
|
||||||
*/
|
*/
|
||||||
@@ -447,11 +442,10 @@ static bool parse_basicConstraints(chunk_t blob, int level0)
|
|||||||
return isCA;
|
return isCA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* extracts an otherName
|
* extracts an otherName
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool parse_otherName(chunk_t blob, int level0)
|
||||||
parse_otherName(chunk_t blob, int level0)
|
|
||||||
{
|
{
|
||||||
asn1_ctx_t ctx;
|
asn1_ctx_t ctx;
|
||||||
chunk_t object;
|
chunk_t object;
|
||||||
@@ -486,7 +480,7 @@ parse_otherName(chunk_t blob, int level0)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* extracts a generalName
|
* extracts a generalName
|
||||||
*/
|
*/
|
||||||
static identification_t *parse_generalName(chunk_t blob, int level0)
|
static identification_t *parse_generalName(chunk_t blob, int level0)
|
||||||
@@ -546,10 +540,10 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* extracts one or several GNs and puts them into a chained list
|
* Defined in header.
|
||||||
*/
|
*/
|
||||||
void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list)
|
void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list)
|
||||||
{
|
{
|
||||||
asn1_ctx_t ctx;
|
asn1_ctx_t ctx;
|
||||||
chunk_t object;
|
chunk_t object;
|
||||||
@@ -591,10 +585,10 @@ static chunk_t parse_keyIdentifier(chunk_t blob, int level0, bool implicit)
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* extracts an authoritykeyIdentifier
|
* Defined in header.
|
||||||
*/
|
*/
|
||||||
void parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber)
|
void x509_parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber)
|
||||||
{
|
{
|
||||||
asn1_ctx_t ctx;
|
asn1_ctx_t ctx;
|
||||||
chunk_t object;
|
chunk_t object;
|
||||||
@@ -743,7 +737,7 @@ static void parse_crlDistributionPoints(chunk_t blob, int level0, linked_list_t
|
|||||||
if (objectID == CRL_DIST_POINTS_FULLNAME)
|
if (objectID == CRL_DIST_POINTS_FULLNAME)
|
||||||
{
|
{
|
||||||
/* append extracted generalNames to existing chained list */
|
/* append extracted generalNames to existing chained list */
|
||||||
parse_generalNames(object, level+1, TRUE, list);
|
x509_parse_generalNames(object, level+1, TRUE, list);
|
||||||
|
|
||||||
}
|
}
|
||||||
objectID++;
|
objectID++;
|
||||||
@@ -790,7 +784,7 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
|
|||||||
this->serialNumber = object;
|
this->serialNumber = object;
|
||||||
break;
|
break;
|
||||||
case X509_OBJ_SIG_ALG:
|
case X509_OBJ_SIG_ALG:
|
||||||
this->sigAlg = parse_algorithmIdentifier(object, level, NULL);
|
this->signatureAlgorithm = parse_algorithmIdentifier(object, level, NULL);
|
||||||
break;
|
break;
|
||||||
case X509_OBJ_ISSUER:
|
case X509_OBJ_ISSUER:
|
||||||
this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
|
this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
|
||||||
@@ -843,7 +837,7 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
|
|||||||
this->subjectKeyID = chunk_clone(parse_keyIdentifier(object, level, FALSE));
|
this->subjectKeyID = chunk_clone(parse_keyIdentifier(object, level, FALSE));
|
||||||
break;
|
break;
|
||||||
case OID_SUBJECT_ALT_NAME:
|
case OID_SUBJECT_ALT_NAME:
|
||||||
parse_generalNames(object, level, FALSE, this->subjectAltNames);
|
x509_parse_generalNames(object, level, FALSE, this->subjectAltNames);
|
||||||
break;
|
break;
|
||||||
case OID_BASIC_CONSTRAINTS:
|
case OID_BASIC_CONSTRAINTS:
|
||||||
this->isCA = parse_basicConstraints(object, level);
|
this->isCA = parse_basicConstraints(object, level);
|
||||||
@@ -852,7 +846,8 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
|
|||||||
parse_crlDistributionPoints(object, level, this->crlDistributionPoints);
|
parse_crlDistributionPoints(object, level, this->crlDistributionPoints);
|
||||||
break;
|
break;
|
||||||
case OID_AUTHORITY_KEY_ID:
|
case OID_AUTHORITY_KEY_ID:
|
||||||
parse_authorityKeyIdentifier(object, level , &this->authKeyID, &this->authKeySerialNumber);
|
x509_parse_authorityKeyIdentifier(object, level,
|
||||||
|
&this->authKeyID, &this->authKeySerialNumber);
|
||||||
break;
|
break;
|
||||||
case OID_AUTHORITY_INFO_ACCESS:
|
case OID_AUTHORITY_INFO_ACCESS:
|
||||||
parse_authorityInfoAccess(object, level, this->ocspAccessLocations);
|
parse_authorityInfoAccess(object, level, this->ocspAccessLocations);
|
||||||
@@ -873,11 +868,14 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case X509_OBJ_ALGORITHM:
|
case X509_OBJ_ALGORITHM:
|
||||||
this->algorithm = parse_algorithmIdentifier(object, level, NULL);
|
|
||||||
if (this->algorithm != this->sigAlg)
|
|
||||||
{
|
{
|
||||||
DBG1(" signature algorithms do not agree");
|
int alg = parse_algorithmIdentifier(object, level, NULL);
|
||||||
return FALSE;
|
|
||||||
|
if (alg != this->signatureAlgorithm)
|
||||||
|
{
|
||||||
|
DBG1(" signature algorithms do not agree");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case X509_OBJ_SIGNATURE:
|
case X509_OBJ_SIGNATURE:
|
||||||
@@ -1136,7 +1134,7 @@ static iterator_t *create_ocspuri_iterator(const private_x509_t *this)
|
|||||||
*/
|
*/
|
||||||
static bool verify(const private_x509_t *this, const rsa_public_key_t *signer)
|
static bool verify(const private_x509_t *this, const rsa_public_key_t *signer)
|
||||||
{
|
{
|
||||||
hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->algorithm);
|
hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->signatureAlgorithm);
|
||||||
|
|
||||||
if (algorithm == HASH_UNKNOWN)
|
if (algorithm == HASH_UNKNOWN)
|
||||||
{
|
{
|
||||||
@@ -1245,6 +1243,101 @@ static void list(private_x509_t *this, FILE *out, bool utc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined in header.
|
||||||
|
*/
|
||||||
|
chunk_t x509_build_generalNames(linked_list_t *list)
|
||||||
|
{
|
||||||
|
linked_list_t *generalNames = linked_list_create();
|
||||||
|
iterator_t *iterator = list->create_iterator(list, TRUE);
|
||||||
|
identification_t *name;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
while (iterator->iterate(iterator, (void**)&name))
|
||||||
|
{
|
||||||
|
asn1_t asn1_type = ASN1_EOC;
|
||||||
|
chunk_t *generalName = malloc_thing(chunk_t);
|
||||||
|
|
||||||
|
switch (name->get_type(name))
|
||||||
|
{
|
||||||
|
case ID_RFC822_ADDR:
|
||||||
|
asn1_type = ASN1_CONTEXT_S_1;
|
||||||
|
break;
|
||||||
|
case ID_FQDN:
|
||||||
|
asn1_type = ASN1_CONTEXT_S_2;
|
||||||
|
break;
|
||||||
|
case ID_DER_ASN1_DN:
|
||||||
|
asn1_type = ASN1_CONTEXT_C_4;
|
||||||
|
break;
|
||||||
|
case ID_DER_ASN1_GN_URI:
|
||||||
|
asn1_type = ASN1_CONTEXT_S_6;
|
||||||
|
break;
|
||||||
|
case ID_IPV4_ADDR:
|
||||||
|
asn1_type = ASN1_CONTEXT_S_7;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*generalName = asn1_simple_object(asn1_type, name->get_encoding(name));
|
||||||
|
len += generalName->len;
|
||||||
|
generalNames->insert_last(generalNames, generalName);
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
iterator_t *iterator = generalNames->create_iterator(generalNames, TRUE);
|
||||||
|
chunk_t names, *generalName;
|
||||||
|
u_char *pos = build_asn1_object(&names, ASN1_SEQUENCE, len);
|
||||||
|
|
||||||
|
while (iterator->iterate(iterator, (void**)&generalName))
|
||||||
|
{
|
||||||
|
memcpy(pos, generalName->ptr, generalName->len);
|
||||||
|
pos += generalName->len;
|
||||||
|
free(generalName->ptr);
|
||||||
|
free(generalName);
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
generalNames->destroy(generalNames);
|
||||||
|
|
||||||
|
return asn1_wrap(ASN1_OCTET_STRING, "m", names);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return chunk_empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined in header.
|
||||||
|
*/
|
||||||
|
chunk_t x509_build_subjectAltNames(linked_list_t *list)
|
||||||
|
{
|
||||||
|
chunk_t generalNames = x509_build_generalNames(list);
|
||||||
|
|
||||||
|
if (generalNames.len)
|
||||||
|
{
|
||||||
|
return asn1_wrap(ASN1_SEQUENCE, "cm",
|
||||||
|
ASN1_subjectAltName_oid,
|
||||||
|
asn1_wrap(ASN1_OCTET_STRING, "m", generalNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return chunk_empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of x509_t.build_encoding.
|
||||||
|
*/
|
||||||
|
static void build_encoding(private_x509_t *this, hash_algorithm_t alg,
|
||||||
|
rsa_private_key_t *private_key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements x509_t.destroy
|
* Implements x509_t.destroy
|
||||||
*/
|
*/
|
||||||
@@ -1314,7 +1407,8 @@ static private_x509_t *x509_create_empty(void)
|
|||||||
this->public.create_crluri_iterator = (iterator_t* (*) (const x509_t*))create_crluri_iterator;
|
this->public.create_crluri_iterator = (iterator_t* (*) (const x509_t*))create_crluri_iterator;
|
||||||
this->public.create_ocspuri_iterator = (iterator_t* (*) (const x509_t*))create_ocspuri_iterator;
|
this->public.create_ocspuri_iterator = (iterator_t* (*) (const x509_t*))create_ocspuri_iterator;
|
||||||
this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify;
|
this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify;
|
||||||
this->public.list = (void(*)(x509_t*, FILE *out, bool utc))list;
|
this->public.list = (void (*) (x509_t*, FILE *out, bool utc))list;
|
||||||
|
this->public.build_encoding = (void (*) (x509_t*,hash_algorithm_t,rsa_private_key_t*))build_encoding;
|
||||||
this->public.destroy = (void (*) (x509_t*))destroy;
|
this->public.destroy = (void (*) (x509_t*))destroy;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -1362,7 +1456,7 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level)
|
|||||||
this->isSelfSigned = FALSE;
|
this->isSelfSigned = FALSE;
|
||||||
if (this->subject->equals(this->subject, this->issuer))
|
if (this->subject->equals(this->subject, this->issuer))
|
||||||
{
|
{
|
||||||
hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->algorithm);
|
hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->signatureAlgorithm);
|
||||||
|
|
||||||
if (algorithm == HASH_UNKNOWN)
|
if (algorithm == HASH_UNKNOWN)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,7 +33,8 @@
|
|||||||
typedef struct x509_t x509_t;
|
typedef struct x509_t x509_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <crypto/rsa/rsa_public_key.h>
|
#include <crypto/rsa/rsa_private_key.h>
|
||||||
|
#include <crypto/hashers/hasher.h>
|
||||||
#include <crypto/certinfo.h>
|
#include <crypto/certinfo.h>
|
||||||
#include <crypto/ca.h>
|
#include <crypto/ca.h>
|
||||||
#include <utils/identification.h>
|
#include <utils/identification.h>
|
||||||
@@ -51,6 +52,7 @@ typedef struct x509_t x509_t;
|
|||||||
* @brief X.509 certificate.
|
* @brief X.509 certificate.
|
||||||
*
|
*
|
||||||
* @b Constructors:
|
* @b Constructors:
|
||||||
|
* - x509_create()
|
||||||
* - x509_create_from_chunk()
|
* - x509_create_from_chunk()
|
||||||
* - x509_create_from_file()
|
* - x509_create_from_file()
|
||||||
*
|
*
|
||||||
@@ -290,7 +292,24 @@ struct x509_t {
|
|||||||
* @param out stream to write to
|
* @param out stream to write to
|
||||||
* @param utc TRUE for UTC times, FALSE for local time
|
* @param utc TRUE for UTC times, FALSE for local time
|
||||||
*/
|
*/
|
||||||
void (*list)(x509_t *this, FILE *out, bool utc);
|
void (*list) (x509_t *this, FILE *out, bool utc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a list of subjectAltNames
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param subjectAltNames list of subjectAltNames to be added
|
||||||
|
*/
|
||||||
|
void (*add_subjectAltNames) (x509_t *this, linked_list_t *subjectAltNames);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Builds a DER-encoded signed X.509 certificate
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param alg hash algorithm used to compute the certificate digest
|
||||||
|
* @param private_key RSA private key used to sign the certificate digest
|
||||||
|
*/
|
||||||
|
void (*build_encoding) (x509_t *this, hash_algorithm_t alg, rsa_private_key_t *private_key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroys the certificate.
|
* @brief Destroys the certificate.
|
||||||
@@ -348,7 +367,7 @@ x509_t *x509_create_from_file(const char *filename, const char *label);
|
|||||||
*
|
*
|
||||||
* @ingroup crypto
|
* @ingroup crypto
|
||||||
*/
|
*/
|
||||||
void parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
|
void x509_parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Parses DER encoded generalNames
|
* @brief Parses DER encoded generalNames
|
||||||
@@ -356,10 +375,30 @@ void parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID,
|
|||||||
* @param blob blob containing DER encoded data
|
* @param blob blob containing DER encoded data
|
||||||
* @param level0 indicates the current parsing level
|
* @param level0 indicates the current parsing level
|
||||||
* @param implicit implicit coding is used
|
* @param implicit implicit coding is used
|
||||||
* @param list linked list of decoded generalNames
|
* @param list list of decoded generalNames
|
||||||
*
|
*
|
||||||
* @ingroup crypto
|
* @ingroup crypto
|
||||||
*/
|
*/
|
||||||
void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list);
|
void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Builds a DER encoded list of generalNames
|
||||||
|
*
|
||||||
|
* @param list list of generalNames to be encoded
|
||||||
|
* @return DER encoded list of generalNames
|
||||||
|
*
|
||||||
|
* @ingroup crypto
|
||||||
|
*/
|
||||||
|
chunk_t x509_build_generalNames(linked_list_t *list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Builds a DER encoded list of subjectAltNames
|
||||||
|
*
|
||||||
|
* @param list list of subjectAltNames to be encoded
|
||||||
|
* @return DER encoded list of subjectAltNames
|
||||||
|
*
|
||||||
|
* @ingroup crypto
|
||||||
|
*/
|
||||||
|
chunk_t x509_build_subjectAltNames(linked_list_t *list);
|
||||||
|
|
||||||
#endif /* X509_H_ */
|
#endif /* X509_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user