[crypto] Generalise x509_parse_bit_string() to asn1_bit_string()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
7deb610881
commit
4aad46ac70
@ -62,6 +62,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
__einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
|
__einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
|
||||||
#define EINFO_EINVAL_ASN1_ALGORITHM \
|
#define EINFO_EINVAL_ASN1_ALGORITHM \
|
||||||
__einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
|
__einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
|
||||||
|
#define EINVAL_BIT_STRING \
|
||||||
|
__einfo_error ( EINFO_EINVAL_BIT_STRING )
|
||||||
|
#define EINFO_EINVAL_BIT_STRING \
|
||||||
|
__einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )
|
||||||
#define ENOTSUP_ALGORITHM \
|
#define ENOTSUP_ALGORITHM \
|
||||||
__einfo_error ( EINFO_ENOTSUP_ALGORITHM )
|
__einfo_error ( EINFO_ENOTSUP_ALGORITHM )
|
||||||
#define EINFO_ENOTSUP_ALGORITHM \
|
#define EINFO_ENOTSUP_ALGORITHM \
|
||||||
@ -295,7 +299,9 @@ int asn1_shrink_any ( struct asn1_cursor *cursor ) {
|
|||||||
*/
|
*/
|
||||||
int asn1_boolean ( const struct asn1_cursor *cursor ) {
|
int asn1_boolean ( const struct asn1_cursor *cursor ) {
|
||||||
struct asn1_cursor contents;
|
struct asn1_cursor contents;
|
||||||
const struct asn1_boolean *boolean;
|
const struct {
|
||||||
|
uint8_t value;
|
||||||
|
} __attribute__ (( packed )) *boolean;
|
||||||
|
|
||||||
/* Enter boolean */
|
/* Enter boolean */
|
||||||
memcpy ( &contents, cursor, sizeof ( contents ) );
|
memcpy ( &contents, cursor, sizeof ( contents ) );
|
||||||
@ -347,6 +353,87 @@ int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse ASN.1 bit string
|
||||||
|
*
|
||||||
|
* @v cursor ASN.1 cursor
|
||||||
|
* @v bits Bit string to fill in
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int asn1_bit_string ( const struct asn1_cursor *cursor,
|
||||||
|
struct asn1_bit_string *bits ) {
|
||||||
|
struct asn1_cursor contents;
|
||||||
|
const struct {
|
||||||
|
uint8_t unused;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __attribute__ (( packed )) *bit_string;
|
||||||
|
size_t len;
|
||||||
|
unsigned int unused;
|
||||||
|
uint8_t unused_mask;
|
||||||
|
const uint8_t *last;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Enter bit string */
|
||||||
|
memcpy ( &contents, cursor, sizeof ( contents ) );
|
||||||
|
if ( ( rc = asn1_enter ( &contents, ASN1_BIT_STRING ) ) != 0 ) {
|
||||||
|
DBGC ( cursor, "ASN1 %p cannot locate bit string:\n", cursor );
|
||||||
|
DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validity checks */
|
||||||
|
if ( contents.len < sizeof ( *bit_string ) ) {
|
||||||
|
DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
|
||||||
|
DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
|
||||||
|
return -EINVAL_BIT_STRING;
|
||||||
|
}
|
||||||
|
bit_string = contents.data;
|
||||||
|
len = ( contents.len - offsetof ( typeof ( *bit_string ), data ) );
|
||||||
|
unused = bit_string->unused;
|
||||||
|
unused_mask = ( 0xff >> ( 8 - unused ) );
|
||||||
|
last = ( bit_string->data + len - 1 );
|
||||||
|
if ( ( unused >= 8 ) ||
|
||||||
|
( ( unused > 0 ) && ( len == 0 ) ) ||
|
||||||
|
( ( *last & unused_mask ) != 0 ) ) {
|
||||||
|
DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
|
||||||
|
DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
|
||||||
|
return -EINVAL_BIT_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate bit string */
|
||||||
|
bits->data = &bit_string->data;
|
||||||
|
bits->len = len;
|
||||||
|
bits->unused = unused;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse ASN.1 bit string that must be an integral number of bytes
|
||||||
|
*
|
||||||
|
* @v cursor ASN.1 cursor
|
||||||
|
* @v bits Bit string to fill in
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
|
||||||
|
struct asn1_bit_string *bits ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Parse bit string */
|
||||||
|
if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Check that there are no unused bits at end of string */
|
||||||
|
if ( bits->unused ) {
|
||||||
|
DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
|
||||||
|
cursor );
|
||||||
|
DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
|
||||||
|
return -EINVAL_BIT_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare two ASN.1 objects
|
* Compare two ASN.1 objects
|
||||||
*
|
*
|
||||||
|
@ -241,7 +241,7 @@ static int rsa_parse_integer ( struct rsa_context *context,
|
|||||||
*/
|
*/
|
||||||
static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
|
static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
|
||||||
struct rsa_context *context = ctx;
|
struct rsa_context *context = ctx;
|
||||||
const struct asn1_bit_string *bit_string;
|
struct asn1_bit_string bits;
|
||||||
struct asn1_cursor modulus;
|
struct asn1_cursor modulus;
|
||||||
struct asn1_cursor exponent;
|
struct asn1_cursor exponent;
|
||||||
struct asn1_cursor cursor;
|
struct asn1_cursor cursor;
|
||||||
@ -274,17 +274,10 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
|
|||||||
asn1_skip ( &cursor, ASN1_SEQUENCE );
|
asn1_skip ( &cursor, ASN1_SEQUENCE );
|
||||||
|
|
||||||
/* Enter subjectPublicKey */
|
/* Enter subjectPublicKey */
|
||||||
asn1_enter ( &cursor, ASN1_BIT_STRING );
|
if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 )
|
||||||
|
|
||||||
/* Check and skip unused-bits byte of bit string */
|
|
||||||
bit_string = cursor.data;
|
|
||||||
if ( ( cursor.len < sizeof ( *bit_string ) ) ||
|
|
||||||
( bit_string->unused != 0 ) ) {
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto err_parse;
|
goto err_parse;
|
||||||
}
|
cursor.data = bits.data;
|
||||||
cursor.data = &bit_string->data;
|
cursor.len = bits.len;
|
||||||
cursor.len -= offsetof ( typeof ( *bit_string ), data );
|
|
||||||
|
|
||||||
/* Enter RSAPublicKey */
|
/* Enter RSAPublicKey */
|
||||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
||||||
|
@ -54,10 +54,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
__einfo_error ( EINFO_EINVAL_ALGORITHM )
|
__einfo_error ( EINFO_EINVAL_ALGORITHM )
|
||||||
#define EINFO_EINVAL_ALGORITHM \
|
#define EINFO_EINVAL_ALGORITHM \
|
||||||
__einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
|
__einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
|
||||||
#define EINVAL_BIT_STRING \
|
|
||||||
__einfo_error ( EINFO_EINVAL_BIT_STRING )
|
|
||||||
#define EINFO_EINVAL_BIT_STRING \
|
|
||||||
__einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid bit string" )
|
|
||||||
#define EINVAL_ALGORITHM_MISMATCH \
|
#define EINVAL_ALGORITHM_MISMATCH \
|
||||||
__einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
|
__einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
|
||||||
#define EINFO_EINVAL_ALGORITHM_MISMATCH \
|
#define EINFO_EINVAL_ALGORITHM_MISMATCH \
|
||||||
@ -154,88 +150,6 @@ static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
|
|||||||
static struct asn1_cursor oid_common_name_cursor =
|
static struct asn1_cursor oid_common_name_cursor =
|
||||||
ASN1_OID_CURSOR ( oid_common_name );
|
ASN1_OID_CURSOR ( oid_common_name );
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse X.509 certificate bit string
|
|
||||||
*
|
|
||||||
* @v cert X.509 certificate
|
|
||||||
* @v bits Bit string to fill in
|
|
||||||
* @v raw ASN.1 cursor
|
|
||||||
* @ret rc Return status code
|
|
||||||
*/
|
|
||||||
static int x509_parse_bit_string ( struct x509_certificate *cert,
|
|
||||||
struct x509_bit_string *bits,
|
|
||||||
const struct asn1_cursor *raw ) {
|
|
||||||
struct asn1_cursor cursor;
|
|
||||||
const struct asn1_bit_string *bit_string;
|
|
||||||
size_t len;
|
|
||||||
unsigned int unused;
|
|
||||||
uint8_t unused_mask;
|
|
||||||
const uint8_t *last;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Enter bit string */
|
|
||||||
memcpy ( &cursor, raw, sizeof ( cursor ) );
|
|
||||||
if ( ( rc = asn1_enter ( &cursor, ASN1_BIT_STRING ) ) != 0 ) {
|
|
||||||
DBGC ( cert, "X509 %p cannot locate bit string:\n", cert );
|
|
||||||
DBGC_HDA ( cert, 0, raw->data, raw->len );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validity checks */
|
|
||||||
if ( cursor.len < sizeof ( *bit_string ) ) {
|
|
||||||
DBGC ( cert, "X509 %p invalid bit string:\n", cert );
|
|
||||||
DBGC_HDA ( cert, 0, raw->data, raw->len );
|
|
||||||
return -EINVAL_BIT_STRING;
|
|
||||||
}
|
|
||||||
bit_string = cursor.data;
|
|
||||||
len = ( cursor.len - offsetof ( typeof ( *bit_string ), data ) );
|
|
||||||
unused = bit_string->unused;
|
|
||||||
unused_mask = ( 0xff >> ( 8 - unused ) );
|
|
||||||
last = ( bit_string->data + len - 1 );
|
|
||||||
if ( ( unused >= 8 ) ||
|
|
||||||
( ( unused > 0 ) && ( len == 0 ) ) ||
|
|
||||||
( ( *last & unused_mask ) != 0 ) ) {
|
|
||||||
DBGC ( cert, "X509 %p invalid bit string:\n", cert );
|
|
||||||
DBGC_HDA ( cert, 0, raw->data, raw->len );
|
|
||||||
return -EINVAL_BIT_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Populate bit string */
|
|
||||||
bits->data = &bit_string->data;
|
|
||||||
bits->len = len;
|
|
||||||
bits->unused = unused;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse X.509 certificate bit string that must be an integral number of bytes
|
|
||||||
*
|
|
||||||
* @v cert X.509 certificate
|
|
||||||
* @v bits Bit string to fill in
|
|
||||||
* @v raw ASN.1 cursor
|
|
||||||
* @ret rc Return status code
|
|
||||||
*/
|
|
||||||
static int x509_parse_integral_bit_string ( struct x509_certificate *cert,
|
|
||||||
struct x509_bit_string *bits,
|
|
||||||
const struct asn1_cursor *raw ) {
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Parse bit string */
|
|
||||||
if ( ( rc = x509_parse_bit_string ( cert, bits, raw ) ) != 0 )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* Check that there are no unused bits at end of string */
|
|
||||||
if ( bits->unused ) {
|
|
||||||
DBGC ( cert, "X509 %p invalid integral bit string:\n", cert );
|
|
||||||
DBGC_HDA ( cert, 0, raw->data, raw->len );
|
|
||||||
return -EINVAL_BIT_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse X.509 certificate version
|
* Parse X.509 certificate version
|
||||||
*
|
*
|
||||||
@ -466,7 +380,7 @@ static int x509_parse_public_key ( struct x509_certificate *cert,
|
|||||||
const struct asn1_cursor *raw ) {
|
const struct asn1_cursor *raw ) {
|
||||||
struct x509_public_key *public_key = &cert->subject.public_key;
|
struct x509_public_key *public_key = &cert->subject.public_key;
|
||||||
struct asn1_algorithm **algorithm = &public_key->algorithm;
|
struct asn1_algorithm **algorithm = &public_key->algorithm;
|
||||||
struct x509_bit_string *raw_bits = &public_key->raw_bits;
|
struct asn1_bit_string *raw_bits = &public_key->raw_bits;
|
||||||
struct asn1_cursor cursor;
|
struct asn1_cursor cursor;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -491,8 +405,11 @@ static int x509_parse_public_key ( struct x509_certificate *cert,
|
|||||||
asn1_skip_any ( &cursor );
|
asn1_skip_any ( &cursor );
|
||||||
|
|
||||||
/* Parse bit string */
|
/* Parse bit string */
|
||||||
if ( ( rc = x509_parse_bit_string ( cert, raw_bits, &cursor ) ) != 0 )
|
if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
|
||||||
|
DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
|
||||||
|
cert, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -569,7 +486,7 @@ static int x509_parse_basic_constraints ( struct x509_certificate *cert,
|
|||||||
static int x509_parse_key_usage ( struct x509_certificate *cert,
|
static int x509_parse_key_usage ( struct x509_certificate *cert,
|
||||||
const struct asn1_cursor *raw ) {
|
const struct asn1_cursor *raw ) {
|
||||||
struct x509_key_usage *usage = &cert->extensions.usage;
|
struct x509_key_usage *usage = &cert->extensions.usage;
|
||||||
struct x509_bit_string bit_string;
|
struct asn1_bit_string bit_string;
|
||||||
const uint8_t *bytes;
|
const uint8_t *bytes;
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -579,8 +496,11 @@ static int x509_parse_key_usage ( struct x509_certificate *cert,
|
|||||||
usage->present = 1;
|
usage->present = 1;
|
||||||
|
|
||||||
/* Parse bit string */
|
/* Parse bit string */
|
||||||
if ( ( rc = x509_parse_bit_string ( cert, &bit_string, raw ) ) != 0 )
|
if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
|
||||||
|
DBGC ( cert, "X509 %p could not parse key usage: %s\n",
|
||||||
|
cert, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse key usage bits */
|
/* Parse key usage bits */
|
||||||
bytes = bit_string.data;
|
bytes = bit_string.data;
|
||||||
@ -1034,7 +954,7 @@ static int x509_parse ( struct x509_certificate *cert,
|
|||||||
const struct asn1_cursor *raw ) {
|
const struct asn1_cursor *raw ) {
|
||||||
struct x509_signature *signature = &cert->signature;
|
struct x509_signature *signature = &cert->signature;
|
||||||
struct asn1_algorithm **signature_algorithm = &signature->algorithm;
|
struct asn1_algorithm **signature_algorithm = &signature->algorithm;
|
||||||
struct x509_bit_string *signature_value = &signature->value;
|
struct asn1_bit_string *signature_value = &signature->value;
|
||||||
struct asn1_cursor cursor;
|
struct asn1_cursor cursor;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -1062,9 +982,12 @@ static int x509_parse ( struct x509_certificate *cert,
|
|||||||
asn1_skip_any ( &cursor );
|
asn1_skip_any ( &cursor );
|
||||||
|
|
||||||
/* Parse signatureValue */
|
/* Parse signatureValue */
|
||||||
if ( ( rc = x509_parse_integral_bit_string ( cert, signature_value,
|
if ( ( rc = asn1_integral_bit_string ( &cursor,
|
||||||
&cursor ) ) != 0 )
|
signature_value ) ) != 0 ) {
|
||||||
|
DBGC ( cert, "X509 %p could not parse signature value: %s\n",
|
||||||
|
cert, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
|
DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
|
||||||
DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );
|
DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );
|
||||||
|
|
||||||
|
@ -200,18 +200,14 @@ struct asn1_algorithm {
|
|||||||
/** Declare an ASN.1 OID-identified algorithm */
|
/** Declare an ASN.1 OID-identified algorithm */
|
||||||
#define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 )
|
#define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 )
|
||||||
|
|
||||||
/** An ASN.1 boolean */
|
|
||||||
struct asn1_boolean {
|
|
||||||
/** Value */
|
|
||||||
uint8_t value;
|
|
||||||
} __attribute__ (( packed ));
|
|
||||||
|
|
||||||
/** An ASN.1 bit string */
|
/** An ASN.1 bit string */
|
||||||
struct asn1_bit_string {
|
struct asn1_bit_string {
|
||||||
/** Number of unused bits */
|
|
||||||
uint8_t unused;
|
|
||||||
/** Data */
|
/** Data */
|
||||||
uint8_t data[0];
|
const void *data;
|
||||||
|
/** Length */
|
||||||
|
size_t len;
|
||||||
|
/** Unused bits at end of data */
|
||||||
|
unsigned int unused;
|
||||||
} __attribute__ (( packed ));
|
} __attribute__ (( packed ));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,6 +232,10 @@ extern int asn1_skip_any ( struct asn1_cursor *cursor );
|
|||||||
extern int asn1_shrink_any ( struct asn1_cursor *cursor );
|
extern int asn1_shrink_any ( struct asn1_cursor *cursor );
|
||||||
extern int asn1_boolean ( const struct asn1_cursor *cursor );
|
extern int asn1_boolean ( const struct asn1_cursor *cursor );
|
||||||
extern int asn1_integer ( const struct asn1_cursor *cursor, int *value );
|
extern int asn1_integer ( const struct asn1_cursor *cursor, int *value );
|
||||||
|
extern int asn1_bit_string ( const struct asn1_cursor *cursor,
|
||||||
|
struct asn1_bit_string *bits );
|
||||||
|
extern int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
|
||||||
|
struct asn1_bit_string *bits );
|
||||||
extern int asn1_compare ( const struct asn1_cursor *cursor1,
|
extern int asn1_compare ( const struct asn1_cursor *cursor1,
|
||||||
const struct asn1_cursor *cursor2 );
|
const struct asn1_cursor *cursor2 );
|
||||||
extern int asn1_algorithm ( const struct asn1_cursor *cursor,
|
extern int asn1_algorithm ( const struct asn1_cursor *cursor,
|
||||||
|
@ -16,16 +16,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
#include <ipxe/refcnt.h>
|
#include <ipxe/refcnt.h>
|
||||||
#include <ipxe/list.h>
|
#include <ipxe/list.h>
|
||||||
|
|
||||||
/** An X.509 bit string */
|
|
||||||
struct x509_bit_string {
|
|
||||||
/** Data */
|
|
||||||
const void *data;
|
|
||||||
/** Length */
|
|
||||||
size_t len;
|
|
||||||
/** Unused bits at end of data */
|
|
||||||
unsigned int unused;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** An X.509 serial number */
|
/** An X.509 serial number */
|
||||||
struct x509_serial {
|
struct x509_serial {
|
||||||
/** Raw serial number */
|
/** Raw serial number */
|
||||||
@ -59,7 +49,7 @@ struct x509_public_key {
|
|||||||
/** Public key algorithm */
|
/** Public key algorithm */
|
||||||
struct asn1_algorithm *algorithm;
|
struct asn1_algorithm *algorithm;
|
||||||
/** Raw public key bit string */
|
/** Raw public key bit string */
|
||||||
struct x509_bit_string raw_bits;
|
struct asn1_bit_string raw_bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An X.509 certificate subject */
|
/** An X.509 certificate subject */
|
||||||
@ -77,7 +67,7 @@ struct x509_signature {
|
|||||||
/** Signature algorithm */
|
/** Signature algorithm */
|
||||||
struct asn1_algorithm *algorithm;
|
struct asn1_algorithm *algorithm;
|
||||||
/** Signature value */
|
/** Signature value */
|
||||||
struct x509_bit_string value;
|
struct asn1_bit_string value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An X.509 certificate basic constraints set */
|
/** An X.509 certificate basic constraints set */
|
||||||
|
Reference in New Issue
Block a user