return asn1_shrink ( cursor, ASN1_ANY );
}
+/**
+ * Enter ASN.1 bit string
+ *
+ * @v cursor ASN.1 cursor
+ * @v unused Unused bits to fill in (or NULL to require all used)
+ * @ret rc Return status code
+ */
+int asn1_enter_bits ( struct asn1_cursor *cursor, unsigned int *unused ) {
+ const struct {
+ uint8_t unused;
+ uint8_t data[0];
+ } __attribute__ (( packed )) *bit_string;
+ const uint8_t *last;
+ unsigned int unused_bits;
+ uint8_t unused_mask;
+ int rc;
+
+ /* Enter bit string */
+ if ( ( rc = asn1_enter ( cursor, ASN1_BIT_STRING ) ) != 0 )
+ return rc;
+
+ /* Check that bit string header exists */
+ if ( cursor->len < sizeof ( *bit_string ) ) {
+ DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ asn1_invalidate_cursor ( cursor );
+ return -EINVAL_BIT_STRING;
+ }
+ bit_string = cursor->data;
+ cursor->data = &bit_string->data;
+ cursor->len -= offsetof ( typeof ( *bit_string ), data );
+ unused_bits = bit_string->unused;
+
+ /* Check validity of unused bits */
+ unused_mask = ( 0xff >> ( 8 - unused_bits ) );
+ last = ( cursor->data + cursor->len - 1 );
+ if ( ( unused_bits >= 8 ) ||
+ ( ( unused_bits > 0 ) && ( cursor->len == 0 ) ) ||
+ ( ( *last & unused_mask ) != 0 ) ) {
+ DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ asn1_invalidate_cursor ( cursor );
+ return -EINVAL_BIT_STRING;
+ }
+
+ /* Record or check number of unused bits, as applicable */
+ if ( unused ) {
+ *unused = unused_bits;
+ } else if ( unused_bits ) {
+ DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
+ cursor );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ asn1_invalidate_cursor ( cursor );
+ return -EINVAL_BIT_STRING;
+ }
+
+ return 0;
+}
+
/**
* Parse value of ASN.1 boolean
*
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
*
digest_final ( digest, digest_ctx, name_digest );
digest_init ( digest, digest_ctx );
digest_update ( digest, digest_ctx,
- ocsp->issuer->subject.public_key.raw_bits.data,
- ocsp->issuer->subject.public_key.raw_bits.len );
+ ocsp->issuer->subject.public_key.value.data,
+ ocsp->issuer->subject.public_key.value.len );
digest_final ( digest, digest_ctx, pubkey_digest );
/* Construct request */
/* Generate SHA1 hash of certificate's public key */
digest_init ( &sha1_algorithm, ctx );
digest_update ( &sha1_algorithm, ctx,
- cert->subject.public_key.raw_bits.data,
- cert->subject.public_key.raw_bits.len );
+ cert->subject.public_key.value.data,
+ cert->subject.public_key.value.len );
digest_final ( &sha1_algorithm, ctx, digest );
/* Compare responder key hash with hash of certificate's public key */
const struct asn1_cursor *raw ) {
struct ocsp_response *response = &ocsp->response;
struct asn1_algorithm **algorithm = &response->algorithm;
- struct asn1_bit_string *signature = &response->signature;
+ struct asn1_cursor *signature = &response->signature;
struct asn1_cursor cursor;
int rc;
asn1_skip_any ( &cursor );
/* Parse signature */
- if ( ( rc = asn1_integral_bit_string ( &cursor, signature ) ) != 0 ) {
+ memcpy ( signature, &cursor, sizeof ( *signature ) );
+ if ( ( rc = asn1_enter_bits ( signature, NULL ) ) != 0 ) {
DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n",
ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
return rc;
static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
struct asn1_cursor *exponent,
const struct asn1_cursor *raw ) {
- struct asn1_bit_string bits;
struct asn1_cursor cursor;
int is_private;
int rc;
asn1_skip ( &cursor, ASN1_SEQUENCE );
/* Enter subjectPublicKey */
- if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 )
- return rc;
- cursor.data = bits.data;
- cursor.len = bits.len;
+ asn1_enter_bits ( &cursor, NULL );
/* Enter RSAPublicKey */
asn1_enter ( &cursor, ASN1_SEQUENCE );
const struct asn1_cursor *raw ) {
struct x509_public_key *public_key = &cert->subject.public_key;
struct asn1_algorithm **algorithm = &public_key->algorithm;
- struct asn1_bit_string *raw_bits = &public_key->raw_bits;
+ struct asn1_cursor *value = &public_key->value;
struct asn1_cursor cursor;
int rc;
cert, (*algorithm)->name );
asn1_skip_any ( &cursor );
- /* Parse bit string */
- if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
+ /* Parse subjectPublicKey */
+ memcpy ( value, &cursor, sizeof ( *value ) );
+ if ( ( rc = asn1_enter_bits ( value, NULL ) ) != 0 ) {
DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
cert, strerror ( rc ) );
return rc;
static int x509_parse_key_usage ( struct x509_certificate *cert,
const struct asn1_cursor *raw ) {
struct x509_key_usage *usage = &cert->extensions.usage;
- struct asn1_bit_string bit_string;
+ struct asn1_cursor cursor;
const uint8_t *bytes;
+ unsigned int unused;
size_t len;
unsigned int i;
int rc;
/* Mark extension as present */
usage->present = 1;
- /* Parse bit string */
- if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
+ /* Enter bit string */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ if ( ( rc = asn1_enter_bits ( &cursor, &unused ) ) != 0 ) {
DBGC ( cert, "X509 %p could not parse key usage: %s\n",
cert, strerror ( rc ) );
return rc;
}
/* Parse key usage bits */
- bytes = bit_string.data;
- len = bit_string.len;
+ bytes = cursor.data;
+ len = cursor.len;
if ( len > sizeof ( usage->bits ) )
len = sizeof ( usage->bits );
for ( i = 0 ; i < len ; i++ ) {
const struct asn1_cursor *raw ) {
struct x509_signature *signature = &cert->signature;
struct asn1_algorithm **signature_algorithm = &signature->algorithm;
- struct asn1_bit_string *signature_value = &signature->value;
+ struct asn1_cursor *signature_value = &signature->value;
struct asn1_cursor cursor;
int rc;
asn1_skip_any ( &cursor );
/* Parse signatureValue */
- if ( ( rc = asn1_integral_bit_string ( &cursor,
- signature_value ) ) != 0 ) {
+ memcpy ( signature_value, &cursor, sizeof ( *signature_value ) );
+ if ( ( rc = asn1_enter_bits ( signature_value, NULL ) ) != 0 ) {
DBGC ( cert, "X509 %p could not parse signature value: %s\n",
cert, strerror ( rc ) );
return rc;
extern struct asn1_algorithm oid_sha512_224_algorithm __asn1_algorithm;
extern struct asn1_algorithm oid_sha512_256_algorithm __asn1_algorithm;
-/** An ASN.1 bit string */
-struct asn1_bit_string {
- /** Data */
- const void *data;
- /** Length */
- size_t len;
- /** Unused bits at end of data */
- unsigned int unused;
-} __attribute__ (( packed ));
-
/**
* Invalidate ASN.1 object cursor
*
extern int asn1_enter_any ( struct asn1_cursor *cursor );
extern int asn1_skip_any ( struct asn1_cursor *cursor );
extern int asn1_shrink_any ( struct asn1_cursor *cursor );
+extern int asn1_enter_bits ( struct asn1_cursor *cursor,
+ unsigned int *unused );
extern int asn1_boolean ( const struct asn1_cursor *cursor );
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,
const struct asn1_cursor *cursor2 );
extern int asn1_algorithm ( const struct asn1_cursor *cursor,
/** Signature algorithm */
struct asn1_algorithm *algorithm;
/** Signature value */
- struct asn1_bit_string signature;
+ struct asn1_cursor signature;
/** Signing certificate */
struct x509_certificate *signer;
};
struct asn1_cursor raw;
/** Public key algorithm */
struct asn1_algorithm *algorithm;
- /** Raw public key bit string */
- struct asn1_bit_string raw_bits;
+ /** Public key value */
+ struct asn1_cursor value;
};
/** An X.509 certificate subject */
/** Signature algorithm */
struct asn1_algorithm *algorithm;
/** Signature value */
- struct asn1_bit_string value;
+ struct asn1_cursor value;
};
/** An X.509 certificate basic constraints set */