/* * Parse one CRLs in DER format and append it to the chained list */ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; mbedtls_x509_crl *crl = chain; /* * Check for valid input */ if( crl == NULL || buf == NULL ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); memset( &sig_oid2, 0, sizeof( mbedtls_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 = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); if( crl->next == NULL ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_ALLOC_FAILED ); } mbedtls_x509_crl_init( crl->next ); crl = crl->next; } /* * Copy raw DER-encoded CRL */ if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) return( MBEDTLS_ERR_X509_ALLOC_FAILED ); memmove( 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 = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } /* * TBSCertList ::= SEQUENCE { */ crl->tbs.p = p; if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_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 = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( ret ); } crl->version++; if( crl->version > 2 ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); } if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, &crl->sig_md, &crl->sig_pk, &crl->sig_opts ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); } /* * issuer Name */ crl->issuer_raw.p = p; if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); } if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( ret ); } crl->issuer_raw.len = p - crl->issuer_raw.p; /* * thisUpdate Time * nextUpdate Time OPTIONAL */ if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( ret ); } if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) { if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && ret != ( MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) { mbedtls_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 ) { mbedtls_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 ) { mbedtls_x509_crl_free( crl ); return( ret ); } } if( p != end ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } end = crl->raw.p + crl->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( ret ); } if( crl->sig_oid.len != sig_oid2.len || memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || sig_params1.len != sig_params2.len || ( sig_params1.len != 0 && memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_SIG_MISMATCH ); } if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) { mbedtls_x509_crl_free( crl ); return( ret ); } if( p != end ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }
/* * Parse a CSR in DER format */ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; mbedtls_x509_buf sig_params; memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); /* * Check for valid input */ if( csr == NULL || buf == NULL ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); mbedtls_x509_csr_init( csr ); /* * first copy the raw DER data */ p = mbedtls_calloc( 1, len = buflen ); if( p == NULL ) return( MBEDTLS_ERR_X509_ALLOC_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 = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } /* * CertificationRequestInfo ::= SEQUENCE { */ csr->cri.p = p; if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_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 ) { mbedtls_x509_csr_free( csr ); return( ret ); } csr->version++; if( csr->version != 1 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); } /* * subject Name */ csr->subject_raw.p = p; if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); } if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } csr->subject_raw.len = p - csr->subject_raw.p; /* * subjectPKInfo SubjectPublicKeyInfo */ if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } /* * attributes [0] Attributes * * The list of possible attributes is open-ended, though RFC 2985 * (PKCS#9) defines a few in section 5.4. We currently don't support any, * so we just ignore them. This is a safe thing to do as the worst thing * that could happen is that we issue a certificate that does not match * the requester's expectations - this cannot cause a violation of our * signature policies. */ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); } p += len; end = csr->raw.p + csr->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING */ if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, &csr->sig_md, &csr->sig_pk, &csr->sig_opts ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); } if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } if( p != end ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }
/* * Parse a CSR in DER format */ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; mbedtls_x509_buf sig_params; memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); /* * Check for valid input */ if( csr == NULL || buf == NULL ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); mbedtls_x509_csr_init( csr ); /* * first copy the raw DER data */ p = mbedtls_calloc( 1, len = buflen ); if( p == NULL ) return( MBEDTLS_ERR_X509_ALLOC_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 = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } /* * CertificationRequestInfo ::= SEQUENCE { */ csr->cri.p = p; if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_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 ) { mbedtls_x509_csr_free( csr ); return( ret ); } csr->version++; if( csr->version != 1 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); } /* * subject Name */ csr->subject_raw.p = p; if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); } if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } csr->subject_raw.len = p - csr->subject_raw.p; /* * subjectPKInfo SubjectPublicKeyInfo */ if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } /* * attributes [0] Attributes */ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_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 = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, &csr->sig_md, &csr->sig_pk, &csr->sig_opts ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); } if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) { mbedtls_x509_csr_free( csr ); return( ret ); } if( p != end ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }