From ea8cfeb1020b57b0397ea0917bb6e466d31e6ac0 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:46:13 +0200 Subject: [PATCH] fixed startcrypto! --- lib/mbedtls-2.1.14/library/pkparse.c | 1680 ++++++++++++-------------- lib/pclsync/pssl.c | 67 +- 2 files changed, 853 insertions(+), 894 deletions(-) diff --git a/lib/mbedtls-2.1.14/library/pkparse.c b/lib/mbedtls-2.1.14/library/pkparse.c index a899082..cbed275 100644 --- a/lib/mbedtls-2.1.14/library/pkparse.c +++ b/lib/mbedtls-2.1.14/library/pkparse.c @@ -27,9 +27,9 @@ #if defined(MBEDTLS_PK_PARSE_C) -#include "mbedtls/pk.h" #include "mbedtls/asn1.h" #include "mbedtls/oid.h" +#include "mbedtls/pk.h" #include @@ -56,15 +56,17 @@ #include "mbedtls/platform.h" #else #include -#define mbedtls_calloc calloc -#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_free free #endif -#if defined(MBEDTLS_FS_IO) || \ - defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +#if defined(MBEDTLS_FS_IO) || defined(MBEDTLS_PKCS12_C) || \ + defined(MBEDTLS_PKCS5_C) /* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; +static void mbedtls_zeroize(void *v, size_t n) { + volatile unsigned char *p = v; + while (n--) + *p++ = 0; } #endif @@ -76,94 +78,87 @@ static void mbedtls_zeroize( void *v, size_t n ) { * A terminating null byte is always appended. It is included in the announced * length only if the data looks like it is PEM encoded. */ -int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) -{ - FILE *f; - long size; +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) { + FILE *f; + long size; - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + if ((f = fopen(path, "rb")) == NULL) + return (MBEDTLS_ERR_PK_FILE_IO_ERROR); - fseek( f, 0, SEEK_END ); - if( ( size = ftell( f ) ) == -1 ) - { - fclose( f ); - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - } - fseek( f, 0, SEEK_SET ); + fseek(f, 0, SEEK_END); + if ((size = ftell(f)) == -1) { + fclose(f); + return (MBEDTLS_ERR_PK_FILE_IO_ERROR); + } + fseek(f, 0, SEEK_SET); - *n = (size_t) size; + *n = (size_t)size; - if( *n + 1 == 0 || - ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) - { - fclose( f ); - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - } + if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { + fclose(f); + return (MBEDTLS_ERR_PK_ALLOC_FAILED); + } - if( fread( *buf, 1, *n, f ) != *n ) - { - fclose( f ); + if (fread(*buf, 1, *n, f) != *n) { + fclose(f); - mbedtls_zeroize( *buf, *n ); - mbedtls_free( *buf ); + mbedtls_zeroize(*buf, *n); + mbedtls_free(*buf); - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - } + return (MBEDTLS_ERR_PK_FILE_IO_ERROR); + } - fclose( f ); + fclose(f); - (*buf)[*n] = '\0'; + (*buf)[*n] = '\0'; - if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) - ++*n; + if (strstr((const char *)*buf, "-----BEGIN ") != NULL) + ++*n; - return( 0 ); + return (0); } /* * Load and parse a private key */ -int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, - const char *path, const char *pwd ) -{ - int ret; - size_t n; - unsigned char *buf; +int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, + const char *pwd) { + int ret; + size_t n; + unsigned char *buf; - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); + if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) + return (ret); - if( pwd == NULL ) - ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); - else - ret = mbedtls_pk_parse_key( ctx, buf, n, - (const unsigned char *) pwd, strlen( pwd ) ); + if (pwd == NULL) + ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0); + else + ret = mbedtls_pk_parse_key(ctx, buf, n, (const unsigned char *)pwd, + strlen(pwd)); - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); + mbedtls_zeroize(buf, n); + mbedtls_free(buf); - return( ret ); + return (ret); } /* * Load and parse a public key */ -int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; +int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) { + int ret; + size_t n; + unsigned char *buf; - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); + if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) + return (ret); - ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + ret = mbedtls_pk_parse_public_key(ctx, buf, n); - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); + mbedtls_zeroize(buf, n); + mbedtls_free(buf); - return( ret ); + return (ret); } #endif /* MBEDTLS_FS_IO */ @@ -176,40 +171,36 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) * -- implicitCurve NULL * } */ -static int pk_get_ecparams( unsigned char **p, const unsigned char *end, - mbedtls_asn1_buf *params ) -{ - int ret; +static int pk_get_ecparams(unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params) { + int ret; - if ( end - *p < 1 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + if (end - *p < 1) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + MBEDTLS_ERR_ASN1_OUT_OF_DATA); - /* Tag may be either OID or SEQUENCE */ - params->tag = **p; - if( params->tag != MBEDTLS_ASN1_OID + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if (params->tag != MBEDTLS_ASN1_OID #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) + && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) #endif - ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - } + ) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + } - if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - params->p = *p; - *p += params->len; + params->p = *p; + *p += params->len; - if( *p != end ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + if (*p != end) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - return( 0 ); + return (0); } #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) @@ -232,212 +223,209 @@ static int pk_get_ecparams( unsigned char **p, const unsigned char *end, * * We only support prime-field as field type, and ignore hash and cofactor. */ -static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_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; +static int pk_group_from_specified(const mbedtls_asn1_buf *params, + mbedtls_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 = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - if( ver < 1 || ver > 3 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + if (ver < 1 || ver > 3) + return (MBEDTLS_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 = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if ((ret = mbedtls_asn1_get_tag( + &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) + return (ret); - end_field = p + len; + 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 = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( ret ); + /* + * 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 = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) + return (ret); - if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || - memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) - { - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - } + if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || + memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { + return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); + } + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + + grp->pbits = mbedtls_mpi_bitlen(&grp->P); + + if (p != end_field) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_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 = mbedtls_asn1_get_tag( + &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) + return (ret); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, + MBEDTLS_ASN1_OCTET_STRING)) != 0 || + (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } + + p += len; + + if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, + MBEDTLS_ASN1_OCTET_STRING)) != 0 || + (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, + MBEDTLS_ASN1_BIT_STRING)) == 0) p += len; - /* Prime-p ::= INTEGER -- Field of size p. */ - if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if (p != end_curve) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - - if( p != end_field ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + /* + * ECPoint ::= OCTET STRING + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != + 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + if ((ret = mbedtls_ecp_point_read_binary( + grp, &grp->G, (const unsigned char *)p, len)) != 0) { /* - * 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 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 = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - end_curve = p + len; - - /* - * FieldElement ::= OCTET STRING - * containing an integer in the case of a prime field - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || - ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + (p[0] != 0x02 && p[0] != 0x03) || + len != mbedtls_mpi_size(&grp->P) + 1 || + mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || + mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || + mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); } + } - p += len; + p += len; - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || - ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + /* + * order INTEGER + */ + if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - p += len; + grp->nbits = mbedtls_mpi_bitlen(&grp->N); - /* Ignore seed BIT STRING OPTIONAL */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) - p += len; + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ - if( p != end_curve ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * ECPoint ::= OCTET STRING - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_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 != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || - ( p[0] != 0x02 && p[0] != 0x03 ) || - len != mbedtls_mpi_size( &grp->P ) + 1 || - mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || - mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || - mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - } - } - - p += len; - - /* - * order INTEGER - */ - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - grp->nbits = mbedtls_mpi_bitlen( &grp->N ); - - /* - * Allow optional elements by purposefully not enforcing p == end here. - */ - - return( 0 ); + return (0); } /* * Find the group id associated with an (almost filled) group as generated by * pk_group_from_specified(), or return an error if unknown. */ -static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) -{ - int ret = 0; - mbedtls_ecp_group ref; - const mbedtls_ecp_group_id *id; +static int pk_group_id_from_group(const mbedtls_ecp_group *grp, + mbedtls_ecp_group_id *grp_id) { + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; - mbedtls_ecp_group_init( &ref ); + mbedtls_ecp_group_init(&ref); - for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) - { - /* Load the group associated to that id */ - mbedtls_ecp_group_free( &ref ); - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); - - /* Compare to the group we were given, starting with easy tests */ - if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && - mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && - /* For Y we may only know the parity bit, so compare only that */ - mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) - { - break; - } + for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { + /* Load the group associated to that id */ + mbedtls_ecp_group_free(&ref); + MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); + /* Compare to the group we were given, starting with easy tests */ + if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && + mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && + mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && + mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && + mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && + mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { + break; } + } cleanup: - mbedtls_ecp_group_free( &ref ); + mbedtls_ecp_group_free(&ref); - *grp_id = *id; + *grp_id = *id; - if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - return( ret ); + return (ret); } /* * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID */ -static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, - mbedtls_ecp_group_id *grp_id ) -{ - int ret; - mbedtls_ecp_group grp; +static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id) { + int ret; + mbedtls_ecp_group grp; - mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_group_init(&grp); - if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) - goto cleanup; + if ((ret = pk_group_from_specified(params, &grp)) != 0) + goto cleanup; - ret = pk_group_id_from_group( &grp, grp_id ); + ret = pk_group_id_from_group(&grp, grp_id); cleanup: - mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_group_free(&grp); - return( ret ); + return (ret); } #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ @@ -449,36 +437,33 @@ cleanup: * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL */ -static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) -{ - int ret; - mbedtls_ecp_group_id grp_id; +static int pk_use_ecparams(const mbedtls_asn1_buf *params, + mbedtls_ecp_group *grp) { + int ret; + mbedtls_ecp_group_id grp_id; - if( params->tag == MBEDTLS_ASN1_OID ) - { - if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) - return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); - } - else - { + if (params->tag == MBEDTLS_ASN1_OID) { + if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) + return (MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE); + } else { #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) - return( ret ); + if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) + return (ret); #else - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); #endif - } + } - /* - * grp may already be initilialized; if so, make sure IDs match - */ - if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) - return( ret ); + if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) + return (ret); - return( 0 ); + return (0); } /* @@ -488,23 +473,21 @@ static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *g * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. */ -static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, - mbedtls_ecp_keypair *key ) -{ - int ret; +static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key) { + int ret; - if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, - (const unsigned char *) *p, end - *p ) ) == 0 ) - { - ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); - } + if ((ret = mbedtls_ecp_point_read_binary( + &key->grp, &key->Q, (const unsigned char *)*p, end - *p)) == 0) { + ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q); + } - /* - * We know mbedtls_ecp_point_read_binary consumed all bytes or failed - */ - *p = (unsigned char *) end; + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *)end; - return( ret ); + return (ret); } #endif /* MBEDTLS_ECP_C */ @@ -515,35 +498,32 @@ static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, * publicExponent INTEGER -- e * } */ -static int pk_get_rsapubkey( unsigned char **p, - const unsigned char *end, - mbedtls_rsa_context *rsa ) -{ - int ret; - size_t len; +static int pk_get_rsapubkey(unsigned char **p, const unsigned char *end, + mbedtls_rsa_context *rsa) { + int ret; + size_t len; - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + if ((ret = mbedtls_asn1_get_tag( + p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + ret); - if( *p + len != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + if (*p + len != end) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + if ((ret = mbedtls_asn1_get_mpi(p, end, &rsa->N)) != 0 || + (ret = mbedtls_asn1_get_mpi(p, end, &rsa->E)) != 0) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + ret); - if( *p != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + if (*p != end) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + if ((ret = mbedtls_rsa_check_pubkey(rsa)) != 0) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY); - rsa->len = mbedtls_mpi_size( &rsa->N ); + rsa->len = mbedtls_mpi_size(&rsa->N); - return( 0 ); + return (0); } #endif /* MBEDTLS_RSA_C */ @@ -553,32 +533,29 @@ static int pk_get_rsapubkey( unsigned char **p, * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ -static int pk_get_pk_alg( unsigned char **p, - const unsigned char *end, - mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) -{ - int ret; - mbedtls_asn1_buf alg_oid; +static int pk_get_pk_alg(unsigned char **p, const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params) { + int ret; + mbedtls_asn1_buf alg_oid; - memset( params, 0, sizeof(mbedtls_asn1_buf) ); + memset(params, 0, sizeof(mbedtls_asn1_buf)); - if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) + return (MBEDTLS_ERR_PK_INVALID_ALG + ret); - if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) + return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - /* - * No parameters with RSA (only for EC) - */ - if( *pk_alg == MBEDTLS_PK_RSA && - ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || - params->len != 0 ) ) - { - return( MBEDTLS_ERR_PK_INVALID_ALG ); - } + /* + * No parameters with RSA (only for EC) + */ + if (*pk_alg == MBEDTLS_PK_RSA && + ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || + params->len != 0)) { + return (MBEDTLS_ERR_PK_INVALID_ALG); + } - return( 0 ); + return (0); } /* @@ -586,143 +563,131 @@ static int pk_get_pk_alg( unsigned char **p, * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ -int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk ) -{ - int ret; - size_t len; - mbedtls_asn1_buf alg_params; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; +int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk) { + int ret; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + if ((ret = mbedtls_asn1_get_tag( + p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - end = *p + len; + end = *p + len; - if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) - return( ret ); + if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) + return (ret); - if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + ret); - if( *p + len != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + if (*p + len != end) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) + return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) - return( ret ); + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) + return (ret); #if defined(MBEDTLS_RSA_C) - if( pk_alg == MBEDTLS_PK_RSA ) - { - ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); - } else + if (pk_alg == MBEDTLS_PK_RSA) { + ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk)); + } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) - { - ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); - if( ret == 0 ) - ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); - } else + if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { + ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp); + if (ret == 0) + ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk)); + } else #endif /* MBEDTLS_ECP_C */ - ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - if( ret == 0 && *p != end ) - ret = MBEDTLS_ERR_PK_INVALID_PUBKEY - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + if (ret == 0 && *p != end) + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - if( ret != 0 ) - mbedtls_pk_free( pk ); + if (ret != 0) + mbedtls_pk_free(pk); - return( ret ); + return (ret); } #if defined(MBEDTLS_RSA_C) /* * Parse a PKCS#1 encoded private RSA key */ -static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, - const unsigned char *key, - size_t keylen ) -{ - int ret; - size_t len; - unsigned char *p, *end; +static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa, + const unsigned char *key, size_t keylen) { + int ret; + size_t len; + unsigned char *p, *end; - p = (unsigned char *) key; - end = p + keylen; + p = (unsigned char *)key; + end = p + keylen; - /* - * This function parses the RSAPrivateKey (PKCS#1) - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if ((ret = mbedtls_asn1_get_tag( + &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - end = p + len; + end = p + len; - if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + if ((ret = mbedtls_asn1_get_int(&p, end, &rsa->ver)) != 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - if( rsa->ver != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); - } + if (rsa->ver != 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_VERSION); + } - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) - { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + if ((ret = mbedtls_asn1_get_mpi(&p, end, &rsa->N)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &rsa->E)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &rsa->D)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &rsa->P)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &rsa->Q)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &rsa->DP)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &rsa->DQ)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &rsa->QP)) != 0) { + mbedtls_rsa_free(rsa); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - rsa->len = mbedtls_mpi_size( &rsa->N ); + rsa->len = mbedtls_mpi_size(&rsa->N); - if( p != end ) - { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } + if (p != end) { + mbedtls_rsa_free(rsa); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } - if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) - { - mbedtls_rsa_free( rsa ); - return( ret ); - } + if ((ret = mbedtls_rsa_check_privkey(rsa)) != 0) { + mbedtls_rsa_free(rsa); + return (ret); + } - return( 0 ); + return (0); } #endif /* MBEDTLS_RSA_C */ @@ -730,128 +695,115 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, /* * Parse a SEC1 encoded private EC key */ -static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, - const unsigned char *key, - size_t keylen ) -{ - int ret; - int version, pubkey_done; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - unsigned char *end2; +static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, + const unsigned char *key, size_t keylen) { + int ret; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *)key; + unsigned char *end = p + keylen; + unsigned char *end2; + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if ((ret = mbedtls_asn1_get_tag( + &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } + + end = p + len; + + if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + + if (version != 1) + return (MBEDTLS_ERR_PK_KEY_INVALID_VERSION); + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != + 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + + if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) { + mbedtls_ecp_keypair_free(eck); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } + + p += len; + + pubkey_done = 0; + if (p != end) { /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } + * Is 'parameters' present? */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { + if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || + (ret = pk_use_ecparams(¶ms, &eck->grp)) != 0) { + mbedtls_ecp_keypair_free(eck); + return (ret); + } + } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + mbedtls_ecp_keypair_free(eck); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); } + } - end = p + len; + if (p != end) { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 1)) == 0) { + end2 = p + len; - if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - if( version != 1 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + if (p + len != end2) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - p += len; - - pubkey_done = 0; - if( p != end ) - { + if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) + pubkey_done = 1; + else { /* - * Is 'parameters' present? + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) - { - if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || - ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( ret ); - } - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); + } + } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + mbedtls_ecp_keypair_free(eck); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); } + } - if( p != end ) - { - /* - * Is 'publickey' present? If not, or if we can't read it (eg because it - * is compressed), create it from the private key. - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) - { - end2 = p + len; + if (!pubkey_done && (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, + &eck->grp.G, NULL, NULL)) != 0) { + mbedtls_ecp_keypair_free(eck); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) { + mbedtls_ecp_keypair_free(eck); + return (ret); + } - if( p + len != end2 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) - pubkey_done = 1; - else - { - /* - * The only acceptable failure mode of pk_get_ecpubkey() above - * is if the point format is not recognized. - */ - if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - } - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - } - - if( ! pubkey_done && - ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, - NULL, NULL ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( ret ); - } - - return( 0 ); + return (0); } #endif /* MBEDTLS_ECP_C */ @@ -868,89 +820,83 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, * PK context on failure. * */ -static int pk_parse_key_pkcs8_unencrypted_der( - mbedtls_pk_context *pk, - const unsigned char* key, - size_t keylen ) -{ - int ret, version; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; +static int pk_parse_key_pkcs8_unencrypted_der(mbedtls_pk_context *pk, + const unsigned char *key, + size_t keylen) { + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *)key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; - /* - * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL } - * - * Version ::= INTEGER - * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * PrivateKey ::= OCTET STRING - * - * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey - */ + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + if ((ret = mbedtls_asn1_get_tag( + &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - end = p + len; + end = p + len; - if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - if( version != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); + if (version != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret); - if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != + 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - if( len < 1 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + if (len < 1) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + MBEDTLS_ERR_ASN1_OUT_OF_DATA); - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) + return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) - return( ret ); + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) + return (ret); #if defined(MBEDTLS_RSA_C) - if( pk_alg == MBEDTLS_PK_RSA ) - { - if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) - { - mbedtls_pk_free( pk ); - return( ret ); - } - } else + if (pk_alg == MBEDTLS_PK_RSA) { + if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) { + mbedtls_pk_free(pk); + return (ret); + } + } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) - { - if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) - { - mbedtls_pk_free( pk ); - return( ret ); - } - } else + if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { + if ((ret = pk_use_ecparams(¶ms, &mbedtls_pk_ec(*pk)->grp)) != 0 || + (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len)) != 0) { + mbedtls_pk_free(pk); + return (ret); + } + } else #endif /* MBEDTLS_ECP_C */ - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - return( 0 ); + return (0); } /* @@ -963,250 +909,223 @@ static int pk_parse_key_pkcs8_unencrypted_der( * */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) -static int pk_parse_key_pkcs8_encrypted_der( - mbedtls_pk_context *pk, - unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret, decrypted = 0; - size_t len; - unsigned char *buf; - unsigned char *p, *end; - mbedtls_asn1_buf pbe_alg_oid, pbe_params; +static int pk_parse_key_pkcs8_encrypted_der(mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, + size_t pwdlen) { + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; #if defined(MBEDTLS_PKCS12_C) - mbedtls_cipher_type_t cipher_alg; - mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; #endif - p = key; - end = p + keylen; + p = key; + end = p + keylen; - if( pwdlen == 0 ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + if (pwdlen == 0) + return (MBEDTLS_ERR_PK_PASSWORD_REQUIRED); - /* - * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) - * - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData - * } - * - * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * EncryptedData ::= OCTET STRING - * - * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo - * - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if ((ret = mbedtls_asn1_get_tag( + &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) { + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); + } - end = p + len; + end = p + len; - if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != + 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - buf = p; + buf = p; - /* - * Decrypt EncryptedData with appropriate PBE - */ + /* + * Decrypt EncryptedData with appropriate PBE + */ #if defined(MBEDTLS_PKCS12_C) - if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) - { - if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, - cipher_alg, md_alg, - pwd, pwdlen, p, len, buf ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { + if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, pwd, pwdlen, p, len, + buf)) != 0) { + if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) + return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); - return( ret ); - } - - decrypted = 1; + return (ret); } - else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) - { - if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, - MBEDTLS_PKCS12_PBE_DECRYPT, - pwd, pwdlen, - p, len, buf ) ) != 0 ) - { - return( ret ); - } - // Best guess for password mismatch when using RC4. If first tag is - // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE - // - if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - - decrypted = 1; + decrypted = 1; + } else if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, + &pbe_alg_oid) == 0) { + if ((ret = mbedtls_pkcs12_pbe_sha1_rc4_128(&pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, pwd, + pwdlen, p, len, buf)) != 0) { + return (ret); } - else + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if (*buf != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) + return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); + + decrypted = 1; + } else #endif /* MBEDTLS_PKCS12_C */ #if defined(MBEDTLS_PKCS5_C) - if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) - { - if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, - p, len, buf ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { + if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, + pwdlen, p, len, buf)) != 0) { + if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) + return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); - return( ret ); - } - - decrypted = 1; + return (ret); } - else + + decrypted = 1; + } else #endif /* MBEDTLS_PKCS5_C */ - { - ((void) pwd); - } + { + ((void)pwd); + } - if( decrypted == 0 ) - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + if (decrypted == 0) + return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); + return (pk_parse_key_pkcs8_unencrypted_der(pk, buf, len)); } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ /* * Parse a private key */ -int mbedtls_pk_parse_key( mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret; - const mbedtls_pk_info_t *pk_info; +int mbedtls_pk_parse_key(mbedtls_pk_context *pk, const unsigned char *key, + size_t keylen, const unsigned char *pwd, + size_t pwdlen) { + int ret; + const mbedtls_pk_info_t *pk_info; #if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; + size_t len; + mbedtls_pem_context pem; - mbedtls_pem_init( &pem ); + mbedtls_pem_init(&pem); #if defined(MBEDTLS_RSA_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - key, pwd, pwdlen, &len ); + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (keylen == 0 || key[keylen - 1] != '\0') + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", key, pwd, + pwdlen, &len); - if( ret == 0 ) - { - pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); + if (ret == 0) { + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || + (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), pem.buf, + pem.buflen)) != 0) { + mbedtls_pk_free(pk); } - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); + + mbedtls_pem_free(&pem); + return (ret); + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) + return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); + else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) + return (MBEDTLS_ERR_PK_PASSWORD_REQUIRED); + else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) + return (ret); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN EC PRIVATE KEY-----", - "-----END EC PRIVATE KEY-----", - key, pwd, pwdlen, &len ); - if( ret == 0 ) - { - pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (keylen == 0 || key[keylen - 1] != '\0') + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", key, pwd, + pwdlen, &len); + if (ret == 0) { + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || + (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), pem.buf, + pem.buflen)) != 0) { + mbedtls_pk_free(pk); } - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); + + mbedtls_pem_free(&pem); + return (ret); + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) + return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); + else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) + return (MBEDTLS_ERR_PK_PASSWORD_REQUIRED); + else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) + return (ret); #endif /* MBEDTLS_ECP_C */ - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", - key, NULL, 0, &len ); - if( ret == 0 ) - { - if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (keylen == 0 || key[keylen - 1] != '\0') + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", key, NULL, 0, + &len); + if (ret == 0) { + if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, pem.buf, pem.buflen)) != + 0) { + mbedtls_pk_free(pk); } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); + + mbedtls_pem_free(&pem); + return (ret); + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) + return (ret); #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN ENCRYPTED PRIVATE KEY-----", - "-----END ENCRYPTED PRIVATE KEY-----", - key, NULL, 0, &len ); - if( ret == 0 ) - { - if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, - pem.buf, pem.buflen, - pwd, pwdlen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (keylen == 0 || key[keylen - 1] != '\0') + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", key, + NULL, 0, &len); + if (ret == 0) { + if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, pwd, + pwdlen)) != 0) { + mbedtls_pk_free(pk); } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); + + mbedtls_pem_free(&pem); + return (ret); + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) + return (ret); #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #else - ((void) pwd); - ((void) pwdlen); + ((void)pwd); + ((void)pwdlen); #endif /* MBEDTLS_PEM_PARSE_C */ /* @@ -1217,121 +1136,106 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, * error */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - { - unsigned char *key_copy; + { + unsigned char *key_copy; - if( keylen == 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + if (keylen == 0) + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) + return (MBEDTLS_ERR_PK_ALLOC_FAILED); - memcpy( key_copy, key, keylen ); + memcpy(key_copy, key, keylen); - ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, - pwd, pwdlen ); + ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, pwd, pwdlen); - mbedtls_zeroize( key_copy, keylen ); - mbedtls_free( key_copy ); - } + mbedtls_zeroize(key_copy, keylen); + mbedtls_free(key_copy); + } - if( ret == 0 ) - return( 0 ); + if (ret == 0) + return (0); - mbedtls_pk_free( pk ); + mbedtls_pk_free(pk); - if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) - { - return( ret ); - } + if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { + return (ret); + } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) - return( 0 ); + if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen)) == 0) + return (0); - mbedtls_pk_free( pk ); + mbedtls_pk_free(pk); #if defined(MBEDTLS_RSA_C) - pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), - key, keylen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - else - { - return( 0 ); - } + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || + (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen)) != 0) { + mbedtls_pk_free(pk); + } else { + return (0); + } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) - pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), - key, keylen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - else - { - return( 0 ); - } + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || + (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), key, keylen)) != 0) { + mbedtls_pk_free(pk); + } else { + return (0); + } #endif /* MBEDTLS_ECP_C */ - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); } /* * Parse a public key */ -int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen ) -{ - int ret; - unsigned char *p; +int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen) { + int ret; + unsigned char *p; #if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; + size_t len; + mbedtls_pem_context pem; - mbedtls_pem_init( &pem ); + mbedtls_pem_init(&pem); - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", - key, NULL, 0, &len ); + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (keylen == 0 || key[keylen - 1] != '\0') + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = + mbedtls_pem_read_buffer(&pem, "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", key, NULL, 0, &len); - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - key = pem.buf; - keylen = pem.buflen; - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } + if (ret == 0) { + /* + * Was PEM encoded + */ + key = pem.buf; + keylen = pem.buflen; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + mbedtls_pem_free(&pem); + return (ret); + } #endif /* MBEDTLS_PEM_PARSE_C */ - p = (unsigned char *) key; + p = (unsigned char *)key; - ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); #if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_free( &pem ); + mbedtls_pem_free(&pem); #endif - return( ret ); + return (ret); } #endif /* MBEDTLS_PK_PARSE_C */ diff --git a/lib/pclsync/pssl.c b/lib/pclsync/pssl.c index 1befa1a..068004d 100644 --- a/lib/pclsync/pssl.c +++ b/lib/pclsync/pssl.c @@ -60,6 +60,42 @@ #include #include +// HACK: This function is duplicated from +// mbedtls-2.1.14/library/pkparse.c, because it is needed to properly +// parse the RSA keys returned by the pcloud server; see the fallback +// code in psync_ssl_rsa_load_public. +// +// IMO this duplication beats the hell out of maintaining the full +// mbedtls library in the pcloudcc source tree just to apply a tiny +// patch. +static int pk_get_rsapubkey(unsigned char **p, const unsigned char *end, + mbedtls_rsa_context *rsa) { + int ret; + size_t len; + + if ((ret = mbedtls_asn1_get_tag( + p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + ret); + + if (*p + len != end) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + + if ((ret = mbedtls_asn1_get_mpi(p, end, &rsa->N)) != 0 || + (ret = mbedtls_asn1_get_mpi(p, end, &rsa->E)) != 0) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + ret); + + if (*p != end) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + + if ((ret = mbedtls_rsa_check_pubkey(rsa)) != 0) + return (MBEDTLS_ERR_PK_INVALID_PUBKEY); + + rsa->len = mbedtls_mpi_size(&rsa->N); + + return (0); +} + static pthread_mutex_t rsa_decr_mutex = PTHREAD_MUTEX_INITIALIZER; static void psync_ssl_free_psync_encrypted_data_t(psync_encrypted_data_t e) { @@ -626,13 +662,32 @@ psync_rsa_publickey_t psync_ssl_rsa_load_public(const unsigned char *keydata, keydata[0], keydata[1], keydata[2], keydata[3]); mbedtls_pk_init(&ctx); + if (unlikely(ret = mbedtls_pk_parse_public_key(&ctx, keydata, keylen))) { - debug(D_WARNING, "pk_parse_public_key failed with code %d (-0x%04x)", ret, - -ret); - char error_buf[100]; - mbedtls_strerror(ret, error_buf, sizeof(error_buf)); - debug(D_WARNING, "Error details: %s", error_buf); - return PSYNC_INVALID_RSA; + debug(D_WARNING, + "pk_parse_public_key failed with code %d (-0x%04x); resorting to " + "mbedtls 1.x RSA fallback", + ret, -ret); + + // this code comes from the mbedtls-1.3.10.patch that was applied + // to the vanilla version. + // + // TODO: fixme + + if (ret != 0) { + mbedtls_pk_setup(&ctx, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); + unsigned char *p = (unsigned char *)keydata; + ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(ctx)); + if (ret != 0) + mbedtls_pk_free(&ctx); + } + + if (ret != 0) { + char error_buf[100]; + mbedtls_strerror(ret, error_buf, sizeof(error_buf)); + debug(D_WARNING, "Error details: %s", error_buf); + return PSYNC_INVALID_RSA; + } } if (mbedtls_pk_get_type(&ctx) != MBEDTLS_PK_RSA) {