diff --git a/include/mbedtls/asn1write.h b/include/mbedtls/asn1write.h index 336f2daf1..c0973393c 100644 --- a/include/mbedtls/asn1write.h +++ b/include/mbedtls/asn1write.h @@ -106,6 +106,26 @@ int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, */ int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); + +/** + * \brief Write a arbitrary-precision number as an + * octet string (#MBEDTLS_ASN1_OCTET_STRING) + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. + * \param len The intended number of octets of the resulting string. + * If the MPI results in less octets, leading zeros is + * added to fill the string. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_mpi_to_octet_string( unsigned char **p, unsigned char *start, + const mbedtls_mpi *X, size_t len ); #endif /* MBEDTLS_BIGNUM_C */ /** diff --git a/library/asn1write.c b/library/asn1write.c index b54e26bd8..f6513c32d 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -161,6 +161,40 @@ int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedt ret = (int) len; +cleanup: + return( ret ); +} + +int mbedtls_asn1_write_mpi_to_octet_string( unsigned char **p, unsigned char *start, const mbedtls_mpi *X, size_t len ) +{ + int ret; + size_t mpi_size; + int i; + + // Write the MPI + // + mpi_size = mbedtls_mpi_size( X ); + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + if( mpi_size > len ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + (*p) -= mpi_size; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, mpi_size ) ); + + for( i = 0; i < (int)(len - mpi_size); i++ ) + { + (*p)--; + **p = 0; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + ret = (int) len; + cleanup: return( ret ); } diff --git a/library/pkwrite.c b/library/pkwrite.c index 438816078..7fa504f44 100644 --- a/library/pkwrite.c +++ b/library/pkwrite.c @@ -424,9 +424,8 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); len += par_len; - /* privateKey: write as MPI then fix tag */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); - *c = MBEDTLS_ASN1_OCTET_STRING; + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi_to_octet_string( &c, buf, &ec->d, ec->d.n * 4 ) ); /* version */ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );