result_t x509_get_username (char *cn, int cn_len, char *x509_username_field, x509_cert *cert) { x509_name *name; ASSERT( cn != NULL ); name = &cert->subject; /* Find common name */ while( name != NULL ) { if( memcmp( name->oid.p, OID_CN, OID_SIZE(OID_CN) ) == 0) break; name = name->next; } /* Not found, return an error if this is the peer's certificate */ if( name == NULL ) return FAILURE; /* Found, extract CN */ if (cn_len > name->val.len) memcpy( cn, name->val.p, name->val.len ); else { memcpy( cn, name->val.p, cn_len); cn[cn_len-1] = '\0'; } return SUCCESS; }
/* * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static int x509_write_name( unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, const unsigned char *name, size_t name_len ) { int ret; size_t len = 0; // Write PrintableString for all except OID_PKCS9_EMAIL // if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len && memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 ) { ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start, (const char *) name, name_len ) ); } else { ASN1_CHK_ADD( len, asn1_write_printable_string( p, start, (const char *) name, name_len ) ); } // Write OID // ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) ); return( (int) len ); }
int x509write_crt_set_basic_constraints( x509write_cert *ctx, int is_ca, int max_pathlen ) { int ret; unsigned char buf[9]; unsigned char *c = buf + sizeof(buf); size_t len = 0; memset( buf, 0, sizeof(buf) ); if( is_ca && max_pathlen > 127 ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); if( is_ca ) { if( max_pathlen >= 0 ) { ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) ); } ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) ); } ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS, OID_SIZE( OID_BASIC_CONSTRAINTS ), 0, buf + sizeof(buf) - len, len ); }
int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ) { int ret; unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ unsigned char *c = buf + sizeof(buf); size_t len = 0; memset( buf, 0, sizeof(buf)); ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) ); sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); c = buf + sizeof(buf) - 20; len = 20; ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER, OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ), 0, buf + sizeof(buf) - len, len ); }
int x509_write_name( unsigned char **p, unsigned char *start, char *oid, char *name ) { int ret; size_t string_len = 0; size_t oid_len = 0; size_t len = 0; // Write PrintableString for all except OID_PKCS9_EMAIL // if( OID_SIZE( OID_PKCS9_EMAIL ) == strlen( oid ) && memcmp( oid, OID_PKCS9_EMAIL, strlen( oid ) ) == 0 ) { ASN1_CHK_ADD( string_len, asn1_write_ia5_string( p, start, name ) ); } else ASN1_CHK_ADD( string_len, asn1_write_printable_string( p, start, name ) ); // Write OID // ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) ); len = oid_len + string_len; ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + string_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) ); return( len ); }
int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage ) { unsigned char buf[4]; unsigned char *c; int ret; c = buf + 4; if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) return( ret ); ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE, OID_SIZE( OID_KEY_USAGE ), buf, 4 ); if( ret != 0 ) return( ret ); return( 0 ); }
int x509write_csr_set_ns_cert_type( x509write_csr *ctx, unsigned char ns_cert_type ) { unsigned char buf[4]; unsigned char *c; int ret; c = buf + 4; if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) return( ret ); ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE, OID_SIZE( OID_NS_CERT_TYPE ), buf, 4 ); if( ret != 0 ) return( ret ); return( 0 ); }
int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ) { int ret; unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ unsigned char *c = buf + sizeof(buf); size_t len = 0; memset( buf, 0, sizeof(buf)); ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) ); sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); c = buf + sizeof(buf) - 20; len = 20; ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) ); return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER, OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ), 0, buf + sizeof(buf) - len, len ); }
int pkcs11_sign( pkcs11_context *ctx, int mode, int hash_id, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t olen, asn_len; unsigned char *p = sig; if( NULL == ctx ) return POLARSSL_ERR_RSA_BAD_INPUT_DATA; if( RSA_PUBLIC == mode ) return POLARSSL_ERR_RSA_BAD_INPUT_DATA; olen = ctx->len; switch( hash_id ) { case SIG_RSA_RAW: asn_len = 0; memcpy( p, hash, hashlen ); break; case SIG_RSA_MD2: asn_len = OID_SIZE(ASN1_HASH_MDX); memcpy( p, ASN1_HASH_MDX, asn_len ); memcpy( p + asn_len, hash, hashlen ); p[13] = 2; break; case SIG_RSA_MD4: asn_len = OID_SIZE(ASN1_HASH_MDX); memcpy( p, ASN1_HASH_MDX, asn_len ); memcpy( p + asn_len, hash, hashlen ); p[13] = 4; break; case SIG_RSA_MD5: asn_len = OID_SIZE(ASN1_HASH_MDX); memcpy( p, ASN1_HASH_MDX, asn_len ); memcpy( p + asn_len, hash, hashlen ); p[13] = 5; break; case SIG_RSA_SHA1: asn_len = OID_SIZE(ASN1_HASH_SHA1); memcpy( p, ASN1_HASH_SHA1, asn_len ); memcpy( p + 15, hash, hashlen ); break; case SIG_RSA_SHA224: asn_len = OID_SIZE(ASN1_HASH_SHA2X); memcpy( p, ASN1_HASH_SHA2X, asn_len ); memcpy( p + asn_len, hash, hashlen ); p[1] += hashlen; p[14] = 4; p[18] += hashlen; break; case SIG_RSA_SHA256: asn_len = OID_SIZE(ASN1_HASH_SHA2X); memcpy( p, ASN1_HASH_SHA2X, asn_len ); memcpy( p + asn_len, hash, hashlen ); p[1] += hashlen; p[14] = 1; p[18] += hashlen; break; case SIG_RSA_SHA384: asn_len = OID_SIZE(ASN1_HASH_SHA2X); memcpy( p, ASN1_HASH_SHA2X, asn_len ); memcpy( p + asn_len, hash, hashlen ); p[1] += hashlen; p[14] = 2; p[18] += hashlen; break; case SIG_RSA_SHA512: asn_len = OID_SIZE(ASN1_HASH_SHA2X); memcpy( p, ASN1_HASH_SHA2X, asn_len ); memcpy( p + asn_len, hash, hashlen ); p[1] += hashlen; p[14] = 3; p[18] += hashlen; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, asn_len + hashlen, sig, &olen ) != CKR_OK ) { return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } return( 0 ); }
int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; pk_type_t pk_alg; /* * Prepare data to be signed in tmp_buf */ c = tmp_buf + sizeof( tmp_buf ); ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); if( len ) { ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ, OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); } ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ); ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Prepare signature */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) { return( ret ); } if( pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) pk_alg = POLARSSL_PK_RSA; else if( pk_can_do( ctx->key, POLARSSL_PK_ECDSA ) ) pk_alg = POLARSSL_PK_ECDSA; else return( POLARSSL_ERR_X509_INVALID_ALG ); if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } /* * Write data to output buffer */ c2 = buf + size; ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, sig_len ) ); if( len > (size_t)( c2 - buf ) ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); c2 -= len; memcpy( c2, c, len ); len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return( (int) len ); }
/* * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. * WARNING: the resulting group should only be used with * pk_group_id_from_specified(), since its base point may not be set correctly * if it was encoded compressed. * * SpecifiedECDomain ::= SEQUENCE { * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), * fieldID FieldID {{FieldTypes}}, * curve Curve, * base ECPoint, * order INTEGER, * cofactor INTEGER OPTIONAL, * hash HashAlgorithm OPTIONAL, * ... * } * * We only support prime-field as field type, and ignore hash and cofactor. */ static int pk_group_from_specified( const asn1_buf *params, ecp_group *grp ) { int ret; unsigned char *p = params->p; const unsigned char * const end = params->p + params->len; const unsigned char *end_field, *end_curve; size_t len; int ver; /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ if( ( ret = asn1_get_int( &p, end, &ver ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ver < 1 || ver > 3 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); /* * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field * fieldType FIELD-ID.&id({IOSet}), * parameters FIELD-ID.&Type({IOSet}{@fieldType}) * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); end_field = p + len; /* * FIELD-ID ::= TYPE-IDENTIFIER * FieldTypes FIELD-ID ::= { * { Prime-p IDENTIFIED BY prime-field } | * { Characteristic-two IDENTIFIED BY characteristic-two-field } * } * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } */ if( ( ret = asn1_get_tag( &p, end_field, &len, ASN1_OID ) ) != 0 ) return( ret ); if( len != OID_SIZE( OID_ANSI_X9_62_PRIME_FIELD ) || memcmp( p, OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) { return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); } p += len; /* Prime-p ::= INTEGER -- Field of size p. */ if( ( ret = asn1_get_shmpi( &p, end_field, &grp->P ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); grp->pbits = shmpi_msb( &grp->P ); if( p != end_field ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); /* * Curve ::= SEQUENCE { * a FieldElement, * b FieldElement, * seed BIT STRING OPTIONAL * -- Shall be present if used in SpecifiedECDomain * -- with version equal to ecdpVer2 or ecdpVer3 * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); end_curve = p + len; /* * FieldElement ::= OCTET STRING * containing an integer in the case of a prime field */ if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || ( ret = shmpi_read_binary( &grp->A, p, len ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } p += len; if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || ( ret = shmpi_read_binary( &grp->B, p, len ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } p += len; /* Ignore seed BIT STRING OPTIONAL */ if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_BIT_STRING ) ) == 0 ) p += len; if( p != end_curve ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); /* * ECPoint ::= OCTET STRING */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ( ret = ecp_point_read_binary( grp, &grp->G, ( const unsigned char *) p, len ) ) != 0 ) { /* * If we can't read the point because it's compressed, cheat by * reading only the X coordinate and the parity bit of Y. */ if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE || ( p[0] != 0x02 && p[0] != 0x03 ) || len != shmpi_size( &grp->P ) + 1 || shmpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || shmpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || shmpi_lset( &grp->G.Z, 1 ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); } } p += len; /* * order INTEGER */ if( ( ret = asn1_get_shmpi( &p, end, &grp->N ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); grp->nbits = shmpi_msb( &grp->N ); /* * Allow optional elements by purposefully not enforcing p == end here. */ return( 0 ); }