/* * 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 ); }
/* * Parse one CRLs in DER format and append it to the chained list */ int x509_crl_parse_der( x509_crl *chain, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; x509_buf sig_params1, sig_params2; x509_crl *crl = chain; /* * Check for valid input */ if( crl == NULL || buf == NULL ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); memset( &sig_params1, 0, sizeof( x509_buf ) ); memset( &sig_params2, 0, sizeof( x509_buf ) ); /* * Add new CRL on the end of the chain if needed. */ while( crl->version != 0 && crl->next != NULL ) crl = crl->next; if( crl->version != 0 && crl->next == NULL ) { crl->next = polarssl_malloc( sizeof( x509_crl ) ); if( crl->next == NULL ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_MALLOC_FAILED ); } x509_crl_init( crl->next ); crl = crl->next; } /* * Copy raw DER-encoded CRL */ if( ( p = polarssl_malloc( buflen ) ) == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memcpy( p, buf, buflen ); crl->raw.p = p; crl->raw.len = buflen; end = p + buflen; /* * CertificateList ::= SEQUENCE { * tbsCertList TBSCertList, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } /* * TBSCertList ::= SEQUENCE { */ crl->tbs.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } end = p + len; crl->tbs.len = end - crl->tbs.p; /* * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } * -- if present, MUST be v2 * * signature AlgorithmIdentifier */ if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || ( ret = x509_get_alg( &p, end, &crl->sig_oid1, &sig_params1 ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } crl->version++; if( crl->version > 2 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); } if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &sig_params1, &crl->sig_md, &crl->sig_pk, &crl->sig_opts ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); } /* * issuer Name */ crl->issuer_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } crl->issuer_raw.len = p - crl->issuer_raw.p; /* * thisUpdate Time * nextUpdate Time OPTIONAL */ if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 ) { if( ret != ( POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) && ret != ( POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_OUT_OF_DATA ) ) { x509_crl_free( crl ); return( ret ); } } /* * revokedCertificates SEQUENCE OF SEQUENCE { * userCertificate CertificateSerialNumber, * revocationDate Time, * crlEntryExtensions Extensions OPTIONAL * -- if present, MUST be v2 * } OPTIONAL */ if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } /* * crlExtensions EXPLICIT Extensions OPTIONAL * -- if present, MUST be v2 */ if( crl->version == 2 ) { ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); if( ret != 0 ) { x509_crl_free( crl ); return( ret ); } } if( p != end ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } end = crl->raw.p + crl->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, &sig_params2 ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } if( crl->sig_oid1.len != crl->sig_oid2.len || memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 || sig_params1.len != sig_params2.len || ( sig_params1.len != 0 && memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_SIG_MISMATCH ); } if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } if( p != end ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }
/* * RSASSA-PSS-params ::= SEQUENCE { * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, * saltLength [2] INTEGER DEFAULT 20, * trailerField [3] INTEGER DEFAULT 1 } * -- Note that the tags in this Sequence are explicit. * * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other * option. Enfore this at parsing time. */ int x509_get_rsassa_pss_params( const x509_buf *params, md_type_t *md_alg, md_type_t *mgf_md, int *salt_len ) { int ret; unsigned char *p; const unsigned char *end, *end2; size_t len; x509_buf alg_id, alg_params; /* First set everything to defaults */ *md_alg = POLARSSL_MD_SHA1; *mgf_md = POLARSSL_MD_SHA1; *salt_len = 20; /* Make sure params is a SEQUENCE and setup bounds */ if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); p = (unsigned char *) params->p; end = p + params->len; if( p == end ) return( 0 ); /* * HashAlgorithm */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) { end2 = p + len; /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) return( ret ); if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p != end2 ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p == end ) return( 0 ); /* * MaskGenAlgorithm */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) { end2 = p + len; /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) return( ret ); /* Only MFG1 is recognised for now */ if( ! OID_CMP( OID_MGF1, &alg_id ) ) return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE + POLARSSL_ERR_OID_NOT_FOUND ); /* Parse HashAlgorithm */ if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) return( ret ); if( p != end2 ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p == end ) return( 0 ); /* * salt_len */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 ) { end2 = p + len; if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p != end2 ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p == end ) return( 0 ); /* * trailer_field (if present, must be 1) */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 ) { int trailer_field; end2 = p + len; if( ( ret = asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p != end2 ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( trailer_field != 1 ) return( POLARSSL_ERR_X509_INVALID_ALG ); } else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) return( POLARSSL_ERR_X509_INVALID_ALG + ret ); if( p != end ) return( POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
/* * Parse one or more certificates and add them to the chain */ int x509_add_certs( x509_cert *chain, unsigned char *buf, int buflen ) { int ret, len; unsigned char *s1, *s2; unsigned char *p, *end; x509_cert *crt; crt = chain; while( crt->version != 0 ) crt = crt->next; /* * check if the certificate is encoded in base64 */ s1 = (unsigned char *) strstr( (char *) buf, "-----BEGIN CERTIFICATE-----" ); if( s1 != NULL ) { s2 = (unsigned char *) strstr( (char *) buf, "-----END CERTIFICATE-----" ); if( s2 == NULL || s2 <= s1 ) return( ERR_X509_CERT_INVALID_PEM ); s1 += 27; if( *s1 == '\r' ) s1++; if( *s1 == '\n' ) s1++; else return( ERR_X509_CERT_INVALID_PEM ); /* * get the DER data length and decode the buffer */ len = 0; ret = base64_decode( NULL, &len, s1, s2 - s1 ); if( ret == ERR_BASE64_INVALID_CHARACTER ) return( ERR_X509_CERT_INVALID_PEM | ret ); if( ( p = (unsigned char *) malloc( len ) ) == NULL ) return( 1 ); if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 ) { free( p ); return( ERR_X509_CERT_INVALID_PEM | ret ); } /* * update the buffer size and offset */ s2 += 25; if( *s2 == '\r' ) s2++; if( *s2 == '\n' ) s2++; else return( ERR_X509_CERT_INVALID_PEM ); buflen -= s2 - buf; buf = s2; } else { /* * nope, copy the raw DER data */ p = (unsigned char *) malloc( len = buflen ); if( p == NULL ) return( 1 ); memcpy( p, buf, buflen ); buflen = 0; } crt->raw.p = p; crt->raw.len = len; end = p + len; /* * Certificate ::= SEQUENCE { * tbsCertificate TBSCertificate, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT ); } if( len != (int) ( end - p ) ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ERR_ASN1_LENGTH_MISMATCH ); } /* * TBSCertificate ::= SEQUENCE { */ crt->tbs.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } end = p + len; crt->tbs.len = end - crt->tbs.p; /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } * * CertificateSerialNumber ::= INTEGER * * signature AlgorithmIdentifier */ if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 || ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->version++; if( crt->version > 3 ) { x509_free_cert( crt ); return( ERR_X509_CERT_UNKNOWN_VERSION ); } if( crt->sig_oid1.len != 9 || memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_UNKNOWN_SIG_ALG ); } if( crt->sig_oid1.p[8] < 2 || crt->sig_oid1.p[8] > 5 ) { x509_free_cert( crt ); return( ERR_X509_CERT_UNKNOWN_SIG_ALG ); } /* * issuer Name */ crt->issuer_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->issuer_raw.len = p - crt->issuer_raw.p; /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } * */ if( ( ret = x509_get_dates( &p, end, &crt->valid_from, &crt->valid_to ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } /* * subject Name */ crt->subject_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->subject_raw.len = p - crt->subject_raw.p; /* * SubjectPublicKeyInfo ::= SEQUENCE * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid, &crt->rsa.N, &crt->rsa.E ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->rsa.len = ( mpi_size( &crt->rsa.N ) + 7 ) >> 3; /* * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * extensions [3] EXPLICIT Extensions OPTIONAL * -- If present, version shall be v3 */ if( crt->version == 2 || crt->version == 3 ) { ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); if( ret != 0 ) { x509_free_cert( crt ); return( ret ); } } if( crt->version == 2 || crt->version == 3 ) { ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); if( ret != 0 ) { x509_free_cert( crt ); return( ret ); } } if( crt->version == 3 ) { ret = x509_get_ext( &p, end, &crt->v3_ext, &crt->ca_istrue, &crt->max_pathlen ); if( ret != 0 ) { x509_free_cert( crt ); return( ret ); } } if( p != end ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ERR_ASN1_LENGTH_MISMATCH ); } end = crt->raw.p + crt->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, 9 ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_SIG_MISMATCH ); } if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } if( p != end ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ERR_ASN1_LENGTH_MISMATCH ); } crt->next = (x509_cert *) malloc( sizeof( x509_cert ) ); if( crt->next == NULL ) { x509_free_cert( crt ); return( 1 ); } crt = crt->next; memset( crt, 0, sizeof( x509_cert ) ); if( buflen > 0 ) return( x509_add_certs( crt, buf, buflen ) ); return( 0 ); }
/* * Parse a CSR in DER format */ int x509_csr_parse_der( x509_csr *csr, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; x509_buf sig_params; memset( &sig_params, 0, sizeof( x509_buf ) ); /* * Check for valid input */ if( csr == NULL || buf == NULL ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); x509_csr_init( csr ); /* * first copy the raw DER data */ p = polarssl_malloc( len = buflen ); if( p == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memcpy( p, buf, buflen ); csr->raw.p = p; csr->raw.len = len; end = p + len; /* * CertificationRequest ::= SEQUENCE { * certificationRequestInfo CertificationRequestInfo, * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } /* * CertificationRequestInfo ::= SEQUENCE { */ csr->cri.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } end = p + len; csr->cri.len = end - csr->cri.p; /* * Version ::= INTEGER { v1(0) } */ if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } if( csr->version != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); } csr->version++; /* * subject Name */ csr->subject_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } csr->subject_raw.len = p - csr->subject_raw.p; /* * subjectPKInfo SubjectPublicKeyInfo */ if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } /* * attributes [0] Attributes */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } // TODO Parse Attributes / extension requests p += len; end = csr->raw.p + csr->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING */ if( ( ret = x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } if( ( ret = x509_get_sig_alg( &csr->sig_oid, &sig_params, &csr->sig_md, &csr->sig_pk, &csr->sig_opts ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); } if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } if( p != end ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }