diff --git a/ChangeLog b/ChangeLog index 9deefa5e2c17..d4600b3c67a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,8 @@ Features * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites from the default list (enabled by default). See https://sweet32.info/SWEET32_CCS16.pdf. + * Add support for writing unencrypted PKCS#8 private keys in PEM and DER + format. Contributed by mvgalen. API Changes * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`. diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 24951a6e1f2b..04247fefb6f5 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -701,6 +701,21 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) */ int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +/** + * \brief This function writes an unencrypted private key to a PKCS#8 + * or SEC8 DER structure. + * + * \param ctx The private key to write. + * \param buf The buffer that will hold the encoded private key. + * \param size The length of the output buffer \p buf. + * + * \return The length of data written on success. + * \return A negative error code on failure. + */ +int mbedtls_pkcs8_write_unencrypted_key_der( mbedtls_pk_context *ctx, + unsigned char *buf, + size_t size ); + /** * \brief Write a public key to a SubjectPublicKeyInfo DER structure * Note: data is written at the end of the buffer! Use the @@ -740,6 +755,21 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, si * \return 0 if successful, or a specific error code */ int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief This function writes an unencrypted private key to a PKCS#8 + * or SEC8 PEM string. + * + * \param ctx The private to write. + * \param buf The buffer that will hold the encoded private key. + * \param size The length of the output buffer \p buf. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_pkcs8_write_unencrypted_key_pem( mbedtls_pk_context *ctx, + unsigned char *buf, + size_t size ); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ diff --git a/library/pkwrite.c b/library/pkwrite.c index b87f81b8b7aa..1df2d8de00d7 100644 --- a/library/pkwrite.c +++ b/library/pkwrite.c @@ -292,6 +292,62 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si return( (int) len ); } +int mbedtls_pkcs8_write_unencrypted_key_der( mbedtls_pk_context *key, + unsigned char *buf, + size_t size ) +{ + int ret; + size_t len; + unsigned char *c; + const char *oid; + size_t oid_len, par_len = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_key_der( key, buf, size ) ) < 0 ) + return( ret ); + + len = ret; + c = buf + size - len; + + /* Wrap PKCS1 key in OCTET STRING */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + + /* privateKeyAlgorithm */ + ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), + &oid, + &oid_len ); + if( ret != 0 ) + return ret; + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, + pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif /* MBEDTLS_ECP_C */ + + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_algorithm_identifier( &c, buf, + oid, oid_len, + par_len ) ); + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + + /* sequence and length */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int)len ); +} + int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) { int ret; @@ -448,6 +504,9 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY "-----END PRIVATE KEY-----\n" + #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" @@ -536,6 +595,17 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ #define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES +/* + * PKCS8 envelope: + * PrivateKeyInfo ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 1 + 1 + 22 + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * } + */ +#define PRV_PKCS8_DER_MAX_BYTES ( 31 + ( PRV_DER_MAX_BYTES ) ) + int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) { int ret; @@ -601,6 +671,36 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_ return( 0 ); } + +int mbedtls_pkcs8_write_unencrypted_key_pem( mbedtls_pk_context *key, + unsigned char *buf, + size_t size ) +{ + int ret; + unsigned char output_buf[PRV_PKCS8_DER_MAX_BYTES]; + const char *begin = PEM_BEGIN_PRIVATE_KEY; + const char *end = PEM_END_PRIVATE_KEY; + size_t olen = 0; + size_t len = 0; + + ret = mbedtls_pkcs8_write_unencrypted_key_der( key, + output_buf, + sizeof( output_buf ) ); + if( ret < 0 ) + return( ret ); + + len = (size_t)ret; + + ret = mbedtls_pem_write_buffer( begin, + end, + output_buf + sizeof( output_buf ) - len, + len, + buf, + size, + &olen ); + + return( ret ); +} #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c index 35fc1498fbdd..471faa5cef51 100644 --- a/programs/pkey/gen_key.c +++ b/programs/pkey/gen_key.c @@ -107,10 +107,14 @@ int dev_random_entropy_poll( void *data, unsigned char *output, #define FORMAT_PEM 0 #define FORMAT_DER 1 +#define SYNTAX_PKCS1 0 +#define SYNTAX_PKCS8 1 + #define DFL_TYPE MBEDTLS_PK_RSA #define DFL_RSA_KEYSIZE 4096 #define DFL_FILENAME "keyfile.key" #define DFL_FORMAT FORMAT_PEM +#define DFL_SYNTAX SYNTAX_PKCS8 #define DFL_USE_DEV_RANDOM 0 #define USAGE \ @@ -121,6 +125,7 @@ int dev_random_entropy_poll( void *data, unsigned char *output, " ec_curve=%%s see below\n" \ " filename=%%s default: keyfile.key\n" \ " format=pem|der default: pem\n" \ + " syntax=pkcs1|pkcs8 default: pkcs1\n" \ USAGE_DEV_RANDOM \ "\n" @@ -159,32 +164,63 @@ struct options int ec_curve; /* curve identifier for EC keys */ const char *filename; /* filename of the key file */ int format; /* the output format to use */ + int syntax; /* the standard syntax to use */ int use_dev_random; /* use /dev/random as entropy source */ } opt; +#define KEY_OUTPUT_BUFFER_LEN 16000 + static int write_private_key( mbedtls_pk_context *key, const char *output_file ) { int ret; FILE *f; - unsigned char output_buf[16000]; + unsigned char output_buf[KEY_OUTPUT_BUFFER_LEN]; unsigned char *c = output_buf; size_t len = 0; - memset(output_buf, 0, 16000); + memset( output_buf, 0, sizeof( output_buf ) ); if( opt.format == FORMAT_PEM ) { - if( ( ret = mbedtls_pk_write_key_pem( key, output_buf, 16000 ) ) != 0 ) - return( ret ); + if( opt.syntax == SYNTAX_PKCS1 ) + { + ret = mbedtls_pk_write_key_pem( key, + output_buf, + sizeof( output_buf ) ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = mbedtls_pkcs8_write_unencrypted_key_pem( key, + output_buf, + sizeof( output_buf ) ); + if( ret != 0 ) + return( ret ); + } len = strlen( (char *) output_buf ); } else { - if( ( ret = mbedtls_pk_write_key_der( key, output_buf, 16000 ) ) < 0 ) - return( ret ); + if( opt.syntax == SYNTAX_PKCS1 ) + { + ret = mbedtls_pk_write_key_der( key, + output_buf, + sizeof( output_buf ) ); + if( ret < 0 ) + return( ret ); + } + else + { + ret = mbedtls_pkcs8_write_unencrypted_key_der( key, + output_buf, + sizeof( output_buf ) ); + if( ret < 0 ) + return( ret ); + } len = ret; - c = output_buf + sizeof(output_buf) - len; + c = output_buf + sizeof( output_buf ) - len; } if( ( f = fopen( output_file, "wb" ) ) == NULL ) @@ -275,6 +311,15 @@ int main( int argc, char *argv[] ) else goto usage; } + else if( strcmp( p, "syntax" ) == 0 ) + { + if( strcmp( q, "pkcs1" ) == 0 ) + opt.syntax = SYNTAX_PKCS1; + else if( strcmp( q, "pkcs8" ) == 0 ) + opt.syntax = SYNTAX_PKCS8; + else + goto usage; + } else if( strcmp( p, "rsa_keysize" ) == 0 ) { opt.rsa_keysize = atoi( q ); diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c index b81530cebc66..309b7aae7730 100644 --- a/programs/pkey/key_app_writer.c +++ b/programs/pkey/key_app_writer.c @@ -79,12 +79,18 @@ #define OUTPUT_FORMAT_PEM 0 #define OUTPUT_FORMAT_DER 1 +#define SYNTAX_PKCS1 0 +#define SYNTAX_PKCS8 1 + +#define DFL_OUTPUT_SYNTAX SYNTAX_PKCS1 + #define USAGE \ "\n usage: key_app_writer param=<>...\n" \ "\n acceptable parameters:\n" \ " mode=private|public default: none\n" \ " filename=%%s default: keyfile.key\n" \ " output_mode=private|public default: none\n" \ + " output_syntax=pkcs1|pkcs8 default: pkcs1\n" \ USAGE_OUT \ "\n" @@ -120,6 +126,7 @@ struct options int output_mode; /* the output mode to use */ const char *output_file; /* where to store the constructed key file */ int output_format; /* the output format to use */ + int output_syntax; /* the output syntax (only for private keys) */ } opt; static int write_public_key( mbedtls_pk_context *key, const char *output_file ) @@ -164,32 +171,63 @@ static int write_public_key( mbedtls_pk_context *key, const char *output_file ) return( 0 ); } -static int write_private_key( mbedtls_pk_context *key, const char *output_file ) +#define KEY_OUTPUT_BUFFER_LEN 16000 + +static int write_private_key( mbedtls_pk_context *key, + const char *output_file ) { int ret; FILE *f; - unsigned char output_buf[16000]; + unsigned char output_buf[KEY_OUTPUT_BUFFER_LEN]; unsigned char *c = output_buf; size_t len = 0; - memset(output_buf, 0, 16000); + memset( output_buf, 0, sizeof( output_buf ) ); #if defined(MBEDTLS_PEM_WRITE_C) if( opt.output_format == OUTPUT_FORMAT_PEM ) { - if( ( ret = mbedtls_pk_write_key_pem( key, output_buf, 16000 ) ) != 0 ) - return( ret ); + if( opt.output_syntax == SYNTAX_PKCS1 ) + { + ret = mbedtls_pk_write_key_pem( key, + output_buf, + sizeof( output_buf ) ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = mbedtls_pkcs8_write_unencrypted_key_pem( key, + output_buf, + sizeof( output_buf ) ); + if( ret != 0 ) + return( ret ); + } len = strlen( (char *) output_buf ); } else -#endif +#endif /* MBEDTLS_PEM_WRITE_C */ { - if( ( ret = mbedtls_pk_write_key_der( key, output_buf, 16000 ) ) < 0 ) - return( ret ); + if( opt.output_syntax == SYNTAX_PKCS1 ) + { + ret = mbedtls_pk_write_key_der( key, + output_buf, + sizeof( output_buf ) ); + if( ret < 0 ) + return( ret ); + } + else + { + ret = mbedtls_pkcs8_write_unencrypted_key_der( key, + output_buf, + sizeof( output_buf ) ); + if( ret < 0 ) + return( ret ); + } len = ret; - c = output_buf + sizeof(output_buf) - len; + c = output_buf + sizeof( output_buf ) - len; } if( ( f = fopen( output_file, "w" ) ) == NULL ) @@ -239,6 +277,7 @@ int main( int argc, char *argv[] ) opt.output_mode = DFL_OUTPUT_MODE; opt.output_file = DFL_OUTPUT_FILENAME; opt.output_format = DFL_OUTPUT_FORMAT; + opt.output_syntax = DFL_OUTPUT_SYNTAX; for( i = 1; i < argc; i++ ) { @@ -256,6 +295,15 @@ int main( int argc, char *argv[] ) else goto usage; } + else if( strcmp( p, "output_syntax" ) == 0 ) + { + if( strcmp( q, "pkcs1" ) == 0 ) + opt.output_syntax = SYNTAX_PKCS1; + else if( strcmp( q, "pkcs8" ) == 0 ) + opt.output_syntax = SYNTAX_PKCS8; + else + goto usage; + } else if( strcmp( p, "output_mode" ) == 0 ) { if( strcmp( q, "private" ) == 0 ) diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile index aa9fc36b4fd0..ed464277ba70 100644 --- a/tests/data_files/Makefile +++ b/tests/data_files/Makefile @@ -15,6 +15,7 @@ OPENSSL ?= openssl FAKETIME ?= faketime MBEDTLS_CERT_WRITE ?= $(PWD)/../../programs/x509/cert_write MBEDTLS_CERT_REQ ?= $(PWD)/../../programs/x509/cert_req +MBEDTLS_GEN_KEY ?= $(PWD)/../../programs/pkey/gen_key ## Build the generated test data. Note that since the final outputs @@ -251,6 +252,32 @@ rsa_pkcs1_4096_aes256.pem: rsa_pkcs1_4096_clear.pem all_final += rsa_pkcs1_4096_aes256.pem keys_rsa_enc_basic_4096: rsa_pkcs1_4096_des.pem rsa_pkcs1_4096_3des.pem rsa_pkcs1_4096_aes128.pem rsa_pkcs1_4096_aes192.pem rsa_pkcs1_4096_aes256.pem +### +### PKCS8 encoded, decrypted RSA keys +### +server1_pkcs8.key: server1.key + $(OPENSSL) pkcs8 -in $< -out $@ -nocrypt -outform PEM -inform PEM -topk8 +all_final += server1_pkcs8.key +rsa4096_pkcs8_prv.pem: rsa4096_prv.pem + $(OPENSSL) pkcs8 -in $< -out $@ -nocrypt -outform PEM -inform PEM -topk8 +all_final += rsa4096_pkcs8_prv.pem +keys_rsa_nonenc_pkcs8: server1_pkcs8.key rsa4096_pkcs8_prv.pem + +### +### PKCS8 encoded, decrypted EC keys +### + +ec_192_prv_pkcs8.pem: + $(MBEDTLS_GEN_KEY) type=ec ec_curve=secp192r1 format=pem syntax=pkcs8 filename=$@ +all_final += ec_192_prv_pkcs8.pem +ec_521_prv_pkcs8.pem: + $(MBEDTLS_GEN_KEY) type=ec ec_curve=secp521r1 format=pem syntax=pkcs8 filename=$@ +all_final += ec_521_prv_pkcs8.pem +ec_bp512_prv_pkcs8.pem: + $(MBEDTLS_GEN_KEY) type=ec ec_curve=brainpoolP512r1 format=pem syntax=pkcs8 filename=$@ +all_final += ec_bp512_prv_pkcs8.pem +keys_ec_nonenc_pkcs8: ec_192_prv_pkcs8 ec_521_prv_pkcs8 ec_bp512_prv_pkcs8 + ### ### PKCS8-v1 encoded, encrypted RSA keys ### diff --git a/tests/data_files/ec_192_prv_pkcs8.pem b/tests/data_files/ec_192_prv_pkcs8.pem new file mode 100644 index 000000000000..53123e26968f --- /dev/null +++ b/tests/data_files/ec_192_prv_pkcs8.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHwCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEYjBgAgEBBBkA1p9IjgKeGg58reLv +++rT+QQmBUi9UKXloAoGCCqGSM49AwEBoTQDMgAEckTDuYp5kYHEv7T+UCMWH+Dg +2ZSqOPfyDawc4A7E5/uiAHWqMb3O/GfF3KKzk4FF +-----END PRIVATE KEY----- diff --git a/tests/data_files/ec_521_prv_pkcs8.pem b/tests/data_files/ec_521_prv_pkcs8.pem new file mode 100644 index 000000000000..600942def2ac --- /dev/null +++ b/tests/data_files/ec_521_prv_pkcs8.pem @@ -0,0 +1,8 @@ +-----BEGIN PRIVATE KEY----- +MIH3AgEAMBAGByqGSM49AgEGBSuBBAAjBIHfMIHcAgEBBEIBiHyn49EBKZYo6mCe +LUrgZXwR3N8ZNeV0mn+SSTCS0x/CMGa+vnXRf0avMNpPF57NTxxaGQdayvcMMNwf +SGe6ri6gBwYFK4EEACOhgYkDgYYABAAvY157OaQT3U2MbqJ+xqGqo+c3YXrECpTe +hP4dN3PI4ml5qr1eJqt7q98Rtn//YhJKW1DDwmTFuLpzVjh0KWogUgCDf3jQRVzb +QAkrSBZdLleVNeslNHjjaAMqpMaQC7HQzK0IY9vab/IqTHT1D9OUojQC3es32Jgx +OW9BItcEnDPn3A== +-----END PRIVATE KEY----- diff --git a/tests/data_files/ec_bp512_prv_pkcs8.pem b/tests/data_files/ec_bp512_prv_pkcs8.pem new file mode 100644 index 000000000000..4dd74f276c2f --- /dev/null +++ b/tests/data_files/ec_bp512_prv_pkcs8.pem @@ -0,0 +1,8 @@ +-----BEGIN PRIVATE KEY----- +MIH5AgEAMBQGByqGSM49AgEGCSskAwMCCAEBDQSB3TCB2gIBAQRAJTKILN2QwGFm +OBA3ocMK/Y3LmmZq3GX847UjWZKmGdz7uE/bYVa7jad+D1HWFJNWWaxdYenhwgKR +/cZrzqwcn6ALBgkrJAMDAggBAQ2hgYUDgYIABIsQIuF0c3hFK6jKe/RcdWMpWxC6 +CsSP/rJ47NuJKKf9L24nlCm09mS5jJ/YMR6QaeATwjyjPTc0+bbGE8Jdp9hYuizj +CeXWw8z8mWu7mGawVs+Z1vzYNV/JzdEa50Fiumz2NPZhs0+OXp2sQdCZsvfJOrgU +0sTs/T/c9kaNJtUN +-----END PRIVATE KEY----- diff --git a/tests/data_files/rsa4096_pkcs8_prv.pem b/tests/data_files/rsa4096_pkcs8_prv.pem new file mode 100644 index 000000000000..5077c32312d2 --- /dev/null +++ b/tests/data_files/rsa4096_pkcs8_prv.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +HoeBj0uwk3tbGhomfWwuYS2bLD3FFJY= +-----END PRIVATE KEY----- diff --git a/tests/data_files/server1_pkcs8.key b/tests/data_files/server1_pkcs8.key new file mode 100644 index 000000000000..143232b38445 --- /dev/null +++ b/tests/data_files/server1_pkcs8.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCpAh89QGrVVVOL +/TbugmUuFWFeib+46EWQ2+6IFlLT8UNQR5YSWWSHa/0r4Eb5c77dz5LhkVvtZqBv +iSl5RYDQg2rVQUN3Xzl8CQRHgrBXOXDto+wVGR6oMwhHwQVCqf1Mw7Tf3QYfTRBR +QGdzEw9A+G2BJV8KsVPGMH4VOaz5Wu5/kp6mBVvnE5eFtSOS2dQkBtUJJYl1B92m +Go8/CRm+rWUsZOuVm9z+QV4XptpsW2nMAroULBYknErczdD3Umdz8S2gI/1+9DHK +LXDKiQsE2y6mT3Buns69WIniU1meblqSZeKIPwyUGaPd5eidlRPtKdurcBLcWspr +F6tSglSxAgMBAAECggEAFon16JFCrhim/7BRNxWksLShO55bNymivWLXOMbhXOp7 +86TYWrIZOgYoyUUrsfDBr4sTJ4nfHJXnJ3i/UzD1sNkV0kLV4IGOhQAe1fqT0c4T +RV3rChVDhWLo48jWDsHkyev/nys2uc3pMyzHnw0Xp655zBNTzXVAmtm0ttfuPYKv +bzIHZWzyrJiUfBXDmNsM6/jcPu9TmCaUgM3QlBG5YCc64/Nk2gmvhJ8kqoc0bFhh +jqkdnWzR05MsgNv8HwpBZqkDaRGZnKJ3YQefDOAtsCwckJ/5tCeFeNe7G1Sytwgv +yehktrOU4zHA0RqaaCVVZbbdR39BGcWAmDlSBwBxEQKBgQDX25h62G3mqbB0n7Xa +gLrN4769ctzIP2CifbdPknrDZhOGV3v85bSgCtAkaCQB1qrSlxPI4iO1NBUwXKB1 +WYIQmbGH/dG609xN7J2pb1+mEoMx6PfYnx4aeIaY0aJyVtx805LwTlManjjnJlv0 +/X7sAeeDXpsaDdiSPkQDgb4cJwKBgQDIcCX/96STxiNASWb7yLMu0WTKYgrRoK0R +70L9EhGEVgF4Vqi0Ll1K02EE6dyfii8wA8OVf/3bIOL04/w88s3drgH1elbeT9JL +kattPlzA6K8Ec2WVlKa7/arPlY8ZyNUI6sEtiXdhavaHcQYogJPTeQShOSIMG8J4 +6lbtwIaXZwKBgEPnCGhcfPX6m0+UjhhWNm1eHzppT5qOlU+ITInzgjrFeY7hJle/ +yrotrJxHRkxtwv7MF6UxvhnacG/uM2u25HtkXbxx0+/5hWvd6xrJtkT/vdWNe6nh +JA8fqveXuopNWL7Lr4V4nhvZefz8zCCdPbfwQWvJ7vCbOm2GuM6BmdQxAoGAT0uG +zP/knQ2Kzpj7Y+qfcIsoS6SD0TC2p1y3bLTkNy1rQXdPIJEjGUIMpMv8GyWoy18B +1jgfbrxQ7T7wgBAyf1uirMGsciCz+m9zmTFNsoebDbC1ZHq9h6uwEpWBWlsIZJGy +wNgcYW7Wfviozgcn9EZxHXMj1BR7WCilIUPEO0sCgYBUB1a+uoPCCgvaEdbexwan +F0T/KAkM7Aed/7UH2CgoA4/mV/YUlqIDF/d5y2g86BlsKab+KIOaKC7vTeV3c75W +gIsMPirHdH4rIAsvvyC1UljNJGIqHOAJneCYqwhVEGrgh/CLDIw0bYFhlADBtIOO +M+2f+Q8F24/M+Pt6uIHKEg== +-----END PRIVATE KEY----- diff --git a/tests/suites/test_suite_pkwrite.data b/tests/suites/test_suite_pkwrite.data index c8ff1773ca33..8b467d5f50c9 100644 --- a/tests/suites/test_suite_pkwrite.data +++ b/tests/suites/test_suite_pkwrite.data @@ -37,3 +37,23 @@ pk_write_key_check:"data_files/ec_521_prv.pem" Private key write check EC Brainpool 512 bits depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_BP512R1_ENABLED pk_write_key_check:"data_files/ec_bp512_prv.pem" + +PKCS#8 private key write check RSA +depends_on:MBEDTLS_RSA_C:MBEDTLS_BASE64_C +pkcs8_write_key_check:"data_files/server1_pkcs8.key" + +PKCS#8 private key write check RSA 4096 +depends_on:MBEDTLS_RSA_C:MBEDTLS_BASE64_C +pkcs8_write_key_check:"data_files/rsa4096_pkcs8_prv.pem" + +PKCS#8 private key write check EC 192 +depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED +pkcs8_write_key_check:"data_files/ec_192_prv_pkcs8.pem" + +PKCS#8 private key write check EC 521 bits +depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED +pkcs8_write_key_check:"data_files/ec_521_prv_pkcs8.pem" + +PKCS#8 private key write check EC Brainpool 512 bits +depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_BP512R1_ENABLED +pkcs8_write_key_check:"data_files/ec_bp512_prv_pkcs8.pem" diff --git a/tests/suites/test_suite_pkwrite.function b/tests/suites/test_suite_pkwrite.function index 43c275ef255c..f93bbe80035c 100644 --- a/tests/suites/test_suite_pkwrite.function +++ b/tests/suites/test_suite_pkwrite.function @@ -72,3 +72,42 @@ exit: mbedtls_pk_free( &key ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_PEM_WRITE_C */ +void pkcs8_write_key_check( char *key_file ) +{ + mbedtls_pk_context key; + unsigned char *buf = NULL; + unsigned char *check_buf = NULL; + size_t buf_len = 4000; + int ret; + FILE *f; + size_t ilen; + + mbedtls_pk_init( &key ); + TEST_ASSERT( mbedtls_pk_parse_keyfile( &key, key_file, NULL ) == 0 ); + + buf = mbedtls_calloc( buf_len, sizeof( unsigned char ) ); + TEST_ASSERT( buf != NULL ); + check_buf = mbedtls_calloc( buf_len, sizeof( unsigned char ) ); + TEST_ASSERT( check_buf != NULL ); + + ret = mbedtls_pkcs8_write_unencrypted_key_pem( &key, buf, buf_len ); + TEST_ASSERT( ret == 0 ); + + f = fopen( key_file, "r" ); + TEST_ASSERT( f != NULL ); + ilen = fread( check_buf, 1, buf_len, f ); + fclose( f ); + + TEST_ASSERT( ilen == strlen( (char *)buf ) ); + TEST_ASSERT( memcmp( (char *)buf, (char *)check_buf, ilen ) == 0 ); + +exit: + if( buf != NULL ) + mbedtls_free( buf ); + if( check_buf != NULL ) + mbedtls_free( check_buf ); + mbedtls_pk_free( &key ); +} +/* END_CASE */