/* * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ static int x509_get_alg( unsigned char **p, unsigned char *end, x509_buf *alg ) { int ret, len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ERR_X509_CERT_INVALID_ALG | ret ); end = *p + len; alg->tag = **p; if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) return( ERR_X509_CERT_INVALID_ALG | ret ); alg->p = *p; *p += alg->len; if( *p == end ) return( 0 ); /* * assume the algorithm parameters must be NULL */ if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 ) return( ERR_X509_CERT_INVALID_ALG | ret ); if( *p != end ) return( ERR_X509_CERT_INVALID_ALG | ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ static svn_error_t * x509_get_alg(const unsigned char **p, const unsigned char *end, x509_buf * alg) { svn_error_t *err; ptrdiff_t len; err = asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); end = *p + len; alg->tag = **p; err = asn1_get_tag(p, end, &alg->len, ASN1_OID); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); alg->p = *p; *p += alg->len; if (*p == end) return SVN_NO_ERROR; /* The OID encoding of 1.2.840.113549.1.1.10 (id-RSASSA-PSS) */ #define OID_RSASSA_PSS "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0a" if (equal(alg->p, alg->len, OID_RSASSA_PSS, sizeof(OID_RSASSA_PSS) - 1)) { /* Skip over algorithm parameters for id-RSASSA-PSS (RFC 8017) * * RSASSA-PSS-params ::= SEQUENCE { * hashAlgorithm [0] HashAlgorithm DEFAULT sha1, * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, * saltLength [2] INTEGER DEFAULT 20, * trailerField [3] TrailerField DEFAULT trailerFieldBC * } */ err = asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); *p += len; } else { /* Algorithm parameters must be NULL for other algorithms */ err = asn1_get_tag(p, end, &len, ASN1_NULL); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); } if (*p != end) { err = svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, NULL, NULL); return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); } return SVN_NO_ERROR; }
/* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static svn_error_t * x509_get_attribute(const unsigned char **p, const unsigned char *end, x509_name *cur, apr_pool_t *result_pool) { svn_error_t *err; ptrdiff_t len; x509_buf *oid; x509_buf *val; err = asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL); end = *p + len; oid = &cur->oid; err = asn1_get_tag(p, end, &oid->len, ASN1_OID); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL); oid->tag = ASN1_OID; oid->p = *p; *p += oid->len; if ((end - *p) < 1) { err = svn_error_create(SVN_ERR_ASN1_OUT_OF_DATA, NULL, NULL); return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL); } if (**p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING && **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING && **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING) { err = svn_error_create(SVN_ERR_ASN1_UNEXPECTED_TAG, NULL, NULL); return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL); } val = &cur->val; val->tag = *(*p)++; err = asn1_get_len(p, end, &val->len); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL); val->p = *p; *p += val->len; cur->next = NULL; if (*p != end) { err = svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, NULL, NULL); return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL); } return SVN_NO_ERROR; }
/* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } * * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } */ static int x509_get_dates( unsigned char **p, unsigned char *end, x509_time *from, x509_time *to ) { int ret, len; char date[64]; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ERR_X509_CERT_INVALID_DATE | ret ); end = *p + len; /* * TODO: also handle GeneralizedTime */ if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 ) return( ERR_X509_CERT_INVALID_DATE | ret ); memset( date, 0, sizeof( date ) ); memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ? len : (int) sizeof( date ) - 1 ); if( sscanf( date, "%2d%2d%2d%2d%2d%2d", &from->year, &from->mon, &from->day, &from->hour, &from->min, &from->sec ) < 5 ) return( ERR_X509_CERT_INVALID_DATE ); from->year += 100 * ( from->year < 90 ); from->year += 1900; *p += len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 ) return( ERR_X509_CERT_INVALID_DATE | ret ); memset( date, 0, sizeof( date ) ); memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ? len : (int) sizeof( date ) - 1 ); if( sscanf( date, "%2d%2d%2d%2d%2d%2d", &to->year, &to->mon, &to->day, &to->hour, &to->min, &to->sec ) < 5 ) return( ERR_X509_CERT_INVALID_DATE ); to->year += 100 * ( to->year < 90 ); to->year += 1900; *p += len; if( *p != end ) return( ERR_X509_CERT_INVALID_DATE | ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ static int x509_get_pubkey( unsigned char **p, unsigned char *end, x509_buf *pk_alg_oid, mpi *N, mpi *E ) { int ret, len; unsigned char *end2; if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 ) return( ret ); /* * only RSA public keys handled at this time */ if( pk_alg_oid->len != 9 || memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 ) return( ERR_X509_CERT_UNKNOWN_PK_ALG ); if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 ) return( ERR_X509_CERT_INVALID_PUBKEY | ret ); if( ( end - *p ) < 1 ) return( ERR_X509_CERT_INVALID_PUBKEY | ERR_ASN1_OUT_OF_DATA ); end2 = *p + len; if( *(*p)++ != 0 ) return( ERR_X509_CERT_INVALID_PUBKEY ); /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ if( ( ret = asn1_get_tag( p, end2, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ERR_X509_CERT_INVALID_PUBKEY | ret ); if( *p + len != end2 ) return( ERR_X509_CERT_INVALID_PUBKEY | ERR_ASN1_LENGTH_MISMATCH ); if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 || ( ret = asn1_get_mpi( p, end2, E ) ) != 0 ) return( ERR_X509_CERT_INVALID_PUBKEY | ret ); if( *p != end ) return( ERR_X509_CERT_INVALID_PUBKEY | ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * Parses and splits an ASN.1 "SEQUENCE OF <tag>" */ int asn1_get_sequence_of( unsigned char **p, const unsigned char *end, asn1_sequence *cur, int tag) { int ret; size_t len; asn1_buf *buf; /* Get main sequence tag */ if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); if( *p + len != end ) return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); while( *p < end ) { buf = &(cur->buf); buf->tag = **p; if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) return( ret ); buf->p = *p; *p += buf->len; /* Allocate and assign next pointer */ if (*p < end) { cur->next = (asn1_sequence *) polarssl_malloc( sizeof( asn1_sequence ) ); if( cur->next == NULL ) return( POLARSSL_ERR_ASN1_MALLOC_FAILED ); memset( cur->next, 0, sizeof( asn1_sequence ) ); cur = cur->next; } } /* Set final sequence entry's next pointer to NULL */ cur->next = NULL; if( *p != end ) return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * X.509 CRL v2 entry extensions (no extensions parsed yet.) */ static int x509_get_crl_entry_ext( unsigned char **p, const unsigned char *end, x509_buf *ext ) { int ret; size_t len = 0; /* OPTIONAL */ if( end <= *p ) return( 0 ); ext->tag = **p; ext->p = *p; /* * Get CRL-entry extension sequence header * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 */ if( ( ret = asn1_get_tag( p, end, &ext->len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) { ext->p = NULL; return( 0 ); } return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); } end = *p + ext->len; if( end != *p + ext->len ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); while( *p < end ) { if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); *p += len; } if( *p != end ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static int x509_get_attr_type_value( unsigned char **p, const unsigned char *end, x509_name *cur ) { int ret; size_t len; x509_buf *oid; x509_buf *val; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); if( ( end - *p ) < 1 ) return( POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA ); oid = &cur->oid; oid->tag = **p; if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); oid->p = *p; *p += oid->len; if( ( end - *p ) < 1 ) return( POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA ); if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING && **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING && **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING && **p != ASN1_BIT_STRING ) return( POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); val = &cur->val; val->tag = *(*p)++; if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); val->p = *p; *p += val->len; cur->next = NULL; return( 0 ); }
int asn1_get_bitstring( unsigned char **p, const unsigned char *end, asn1_bitstring *bs) { int ret; /* Certificate type is a single byte bitstring */ if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 ) return( ret ); /* Check length, subtract one for actual bit string length */ if ( bs->len < 1 ) return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); bs->len -= 1; /* Get number of unused bits, ensure unused bits <= 7 */ bs->unused_bits = **p; if( bs->unused_bits > 7 ) return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); (*p)++; /* Get actual bitstring */ bs->p = *p; *p += bs->len; if( *p != end ) return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return 0; }
/* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } * * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } */ static svn_error_t * x509_get_dates(apr_time_t *from, apr_time_t *to, const unsigned char **p, const unsigned char *end, apr_pool_t *scratch_pool) { svn_error_t *err; ptrdiff_t len; err = asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); if (err) return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, err, NULL); end = *p + len; SVN_ERR(x509_get_date(from, p, end, scratch_pool)); SVN_ERR(x509_get_date(to, p, end, scratch_pool)); if (*p != end) { err = svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, NULL, NULL); return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, err, NULL); } return SVN_NO_ERROR; }
/* * X.509 v2/v3 unique identifier (not parsed) */ static svn_error_t * x509_get_uid(const unsigned char **p, const unsigned char *end, x509_buf * uid, int n) { svn_error_t *err; if (*p == end) return SVN_NO_ERROR; err = asn1_get_tag(p, end, &uid->len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n); if (err) { if (err->apr_err == SVN_ERR_ASN1_UNEXPECTED_TAG) { svn_error_clear(err); return SVN_NO_ERROR; } return svn_error_trace(err); } uid->tag = ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n; uid->p = *p; *p += uid->len; return SVN_NO_ERROR; }
/* * X.509 CRL v2 extensions (no extensions parsed yet.) */ static int x509_get_crl_ext( unsigned char **p, const unsigned char *end, x509_buf *ext ) { int ret; size_t len = 0; /* Get explicit tag */ if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 ) { if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) return( 0 ); return( ret ); } while( *p < end ) { if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); *p += len; } if( *p != end ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } */ static int x509_get_dates( unsigned char **p, const unsigned char *end, x509_time *from, x509_time *to ) { int ret; size_t len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_DATE + ret ); end = *p + len; if( ( ret = x509_get_time( p, end, from ) ) != 0 ) return( ret ); if( ( ret = x509_get_time( p, end, to ) ) != 0 ) return( ret ); if( *p != end ) return( POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ static int pk_get_shrsapubkey( unsigned char **p, const unsigned char *end, shrsa_t *shrsa ) { int ret; size_t len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); if( *p + len != end ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( ( ret = asn1_get_shmpi( p, end, &shrsa->N ) ) != 0 || ( ret = asn1_get_shmpi( p, end, &shrsa->E ) ) != 0 ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); if( *p != end ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( ( ret = shrsa_check_pubkey( shrsa ) ) != 0 ) return( POLARSSL_ERR_PK_INVALID_PUBKEY ); shrsa->len = shmpi_size( &shrsa->N ); return( 0 ); }
/* Minimally parse an ECParameters buffer to and asn1_buf * * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL * } */ static int pk_get_ecparams( unsigned char **p, const unsigned char *end, asn1_buf *params ) { int ret; /* Tag may be either OID or SEQUENCE */ params->tag = **p; if( params->tag != ASN1_OID #if defined(POLARSSL_PK_PARSE_EC_EXTENDED) && params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) #endif ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); } if( ( ret = asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } params->p = *p; *p += params->len; if( *p != end ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * X.509 v2/v3 unique identifier (not parsed) */ static int x509_get_uid( unsigned char **p, unsigned char *end, x509_buf *uid, int n ) { int ret; if( *p == end ) return( 0 ); uid->tag = **p; if( ( ret = asn1_get_tag( p, end, &uid->len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 ) { if( ret == ERR_ASN1_UNEXPECTED_TAG ) return( 0 ); return( ret ); } uid->p = *p; *p += uid->len; return( 0 ); }
/* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ static int x509_get_version( unsigned char **p, const unsigned char *end, int *ver ) { int ret; size_t len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 ) { if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) { *ver = 0; return( 0 ); } return( ret ); } end = *p + len; if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_VERSION + ret ); if( *p != end ) return( POLARSSL_ERR_X509_INVALID_VERSION + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ static int x509_get_version( unsigned char **p, unsigned char *end, int *ver ) { int ret, len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 ) { if( ret == ERR_ASN1_UNEXPECTED_TAG ) return( *ver = 0 ); return( ret ); } end = *p + len; if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) return( ERR_X509_CERT_INVALID_VERSION | ret ); if( *p != end ) return( ERR_X509_CERT_INVALID_VERSION | ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * HashAlgorithm ::= AlgorithmIdentifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } * * For HashAlgorithm, parameters MUST be NULL or absent. */ static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg ) { int ret; unsigned char *p; const unsigned char *end; x509_buf md_oid; size_t len; /* Make sure we got a SEQUENCE and setup bounds */ if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); p = (unsigned char *) alg->p; end = p + alg->len; if( p >= end ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA ); /* Parse md_oid */ md_oid.tag = *p; if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); md_oid.p = p; p += md_oid.len; /* Get md_alg from md_oid */ if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); /* Make sure params is absent of NULL */ if( p == end ) return( 0 ); if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p != end ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ int pk_parse_subpubkey( unsigned char **p, const unsigned char *end, pk_context *pk ) { int ret; size_t len; asn1_buf alg_params; pk_type_t pk_alg = POLARSSL_PK_NONE; const pk_info_t *pk_info; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } end = *p + len; if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) return( ret ); if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); if( *p + len != end ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 ) return( ret ); #if defined(POLARSSL_RSA_C) if( pk_alg == POLARSSL_PK_RSA ) { ret = pk_get_shrsapubkey( p, end, pk_rsa( *pk ) ); } else #endif /* POLARSSL_RSA_C */ #if defined(POLARSSL_ECP_C) if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY ) { ret = pk_use_ecparams( &alg_params, &pk_ec( *pk )->grp ); if( ret == 0 ) ret = pk_get_ecpubkey( p, end, pk_ec( *pk ) ); } else #endif /* POLARSSL_ECP_C */ ret = POLARSSL_ERR_PK_UNKNOWN_PK_ALG; if( ret == 0 && *p != end ) ret = POLARSSL_ERR_PK_INVALID_PUBKEY POLARSSL_ERR_ASN1_LENGTH_MISMATCH; if( ret != 0 ) pk_free( pk ); return( ret ); }
int cache_public_key(VCRYPT_CTX *ctx, const char *username, VCRYPT_PACKET *packet) { int ret; // add dummy entry if (!packet) { rsa_context *pk = public_key_list_get(ctx->public_keys, username); if (pk) { ret = public_key_node_update(pk, NULL, NULL ); } else { ret = public_key_list_add(&ctx->public_keys, username, NULL, NULL ); } return ret ? ret : -ERR_NO_PUBKEY; } unsigned char *p = (unsigned char*) packet->payload; unsigned char *end = p + packet->payload_len; size_t len = 0; mpi N, E; if ((ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) return -ERR_NO_PUBKEY; if (p + len != end) return -ERR_NO_PUBKEY; mpi_init(&N); mpi_init(&E); if ((ret = asn1_get_mpi(&p, end, &N)) != 0 || (ret = asn1_get_mpi(&p, end, &E)) != 0) { mpi_free(&N); mpi_free(&E); return -ERR_NO_PUBKEY; } if (p != end) { mpi_free(&N); mpi_free(&E); return -ERR_NO_PUBKEY; } rsa_context *pk = public_key_list_get(ctx->public_keys, username); if (pk) { ret = public_key_node_update(pk, &E, &N); } else { ret = public_key_list_add(&ctx->public_keys, username, &E, &N); } mpi_free(&N); mpi_free(&E); return ret; }
SSL_ROM_TEXT_SECTION int asn1_get_alg( unsigned char **p, const unsigned char *end, asn1_buf *alg, asn1_buf *params ) { int ret; size_t len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); if( ( end - *p ) < 1 ) return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); alg->tag = **p; end = *p + len; if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) return( ret ); alg->p = *p; *p += alg->len; if( *p == end ) { memset( params, 0, sizeof(asn1_buf) ); return( 0 ); } params->tag = **p; (*p)++; if( ( ret = asn1_get_len( p, end, ¶ms->len ) ) != 0 ) return( ret ); params->p = *p; *p += params->len; if( *p != end ) return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * Name ::= CHOICE { -- only one possibility for now -- * rdnSequence RDNSequence } * * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * * The data structure is optimized for the common case where each RDN has only * one element, which is represented as a list of AttributeTypeAndValue. * For the general case we still use a flat list, but we mark elements of the * same set so that they are "merged" together in the functions that consume * this list, eg x509_dn_gets(). */ int x509_get_name( unsigned char **p, const unsigned char *end, x509_name *cur ) { int ret; size_t set_len; const unsigned char *end_set; /* don't use recursion, we'd risk stack overflow if not optimized */ while( 1 ) { /* * parse SET */ if( ( ret = asn1_get_tag( p, end, &set_len, ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); end_set = *p + set_len; while( 1 ) { if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) return( ret ); if( *p == end_set ) break; /* Mark this item as being not the only one in a set */ cur->next_merged = 1; cur->next = polarssl_malloc( sizeof( x509_name ) ); if( cur->next == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memset( cur->next, 0, sizeof( x509_name ) ); cur = cur->next; } /* * continue until end of SEQUENCE is reached */ if( *p == end ) return( 0 ); cur->next = polarssl_malloc( sizeof( x509_name ) ); if( cur->next == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memset( cur->next, 0, sizeof( x509_name ) ); cur = cur->next; } }
int rsa_parse_public_key( rsa_context *rsa, unsigned char *buf, int buflen ) { unsigned char *p, *end; int ret, len; p = buf; end = buf+buflen; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) == 0 ) { /* Skip over embedded rsaEncryption Object */ p+=len; /* The RSAPublicKey ASN1 container is wrapped in a BIT STRING */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_BIT_STRING ) ) != 0 ) { return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } /* Limit range to that BIT STRING */ end = p + len; p++; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } } if ( ( ( ret = asn1_get_mpi( &p, end, &(rsa->N) ) ) == 0 ) && ( ( ret = asn1_get_mpi( &p, end, &(rsa->E) ) ) == 0 ) ) { rsa->len = mpi_size( &rsa->N ); return 0; } return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); }
/* * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ int x509_get_name( unsigned char **p, const unsigned char *end, x509_name *cur ) { int ret; size_t len; const unsigned char *end2; x509_name *use; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); end2 = end; end = *p + len; use = cur; do { if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 ) return( ret ); if( *p != end ) { use->next = (x509_name *) polarssl_malloc( sizeof( x509_name ) ); if( use->next == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memset( use->next, 0, sizeof( x509_name ) ); use = use->next; } } while( *p != end ); /* * recurse until end of SEQUENCE is reached */ if( *p == end2 ) return( 0 ); cur->next = (x509_name *) polarssl_malloc( sizeof( x509_name ) ); if( cur->next == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memset( cur->next, 0, sizeof( x509_name ) ); return( x509_get_name( p, end2, cur->next ) ); }
/* * Get a bit string without unused bits */ int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, size_t *len ) { int ret; if( ( ret = asn1_get_tag( p, end, len, ASN1_BIT_STRING ) ) != 0 ) return( ret ); if( (*len)-- < 2 || *(*p)++ != 0 ) return( POLARSSL_ERR_ASN1_INVALID_DATA ); return( 0 ); }
static int x509_get_basic_constraints( unsigned char **p, const unsigned char *end, int *ca_istrue, int *max_pathlen ) { int ret; size_t len; /* * BasicConstraints ::= SEQUENCE { * cA BOOLEAN DEFAULT FALSE, * pathLenConstraint INTEGER (0..MAX) OPTIONAL } */ *ca_istrue = 0; /* DEFAULT FALSE */ *max_pathlen = 0; /* endless */ if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); if( *p == end ) return 0; if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 ) { if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) ret = asn1_get_int( p, end, ca_istrue ); if( ret != 0 ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); if( *ca_istrue != 0 ) *ca_istrue = 1; } if( *p == end ) return 0; if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); if( *p != end ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); (*max_pathlen)++; return 0; }
static int asn1_get_mpi( unsigned char **p, const unsigned char *end, mpi *X ) { int ret, len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) return( ret ); ret = mpi_read_binary( X, *p, len ); *p += len; return( ret ); }
/* * X.509 Extensions (No parsing of extensions, pointer should * be either manually updated or extensions should be parsed! */ int x509_get_ext( unsigned char **p, const unsigned char *end, x509_buf *ext, int tag ) { int ret; size_t len; if( *p == end ) return( 0 ); ext->tag = **p; if( ( ret = asn1_get_tag( p, end, &ext->len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 ) return( ret ); ext->p = *p; end = *p + ext->len; /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension * * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING } */ if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); if( end != *p + len ) return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
SSL_ROM_TEXT_SECTION int asn1_get_mpi( unsigned char **p, const unsigned char *end, mpi *X ) { int ret; size_t len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) return( ret ); ret = mpi_read_binary( X, *p, len ); *p += len; return( ret ); }