mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
fido commands hash checks works.
This commit is contained in:
parent
679b5eec5b
commit
7214c70720
9 changed files with 691 additions and 7 deletions
|
@ -107,6 +107,7 @@ CMDSRCS = crapto1/crapto1.c \
|
||||||
crapto1/crypto1.c \
|
crapto1/crypto1.c \
|
||||||
mfkey.c \
|
mfkey.c \
|
||||||
tea.c \
|
tea.c \
|
||||||
|
fido/additional_ca.c \
|
||||||
polarssl/des.c \
|
polarssl/des.c \
|
||||||
crypto/libpcrypto.c\
|
crypto/libpcrypto.c\
|
||||||
crypto/asn1utils.c\
|
crypto/asn1utils.c\
|
||||||
|
|
|
@ -41,6 +41,10 @@
|
||||||
#include "cliparser/cliparser.h"
|
#include "cliparser/cliparser.h"
|
||||||
#include "crypto/asn1utils.h"
|
#include "crypto/asn1utils.h"
|
||||||
#include "crypto/libpcrypto.h"
|
#include "crypto/libpcrypto.h"
|
||||||
|
#include "fido/additional_ca.h"
|
||||||
|
#include "mbedtls/x509_crt.h"
|
||||||
|
#include "mbedtls/x509.h"
|
||||||
|
#include "mbedtls/pk.h"
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
@ -203,7 +207,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
||||||
void* argtable[] = {
|
void* argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||||
arg_lit0("vV", "verbose", "show technical data"),
|
arg_lit0("vV", "verbose", "show technical data. vv - show full certificates data"),
|
||||||
arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"),
|
arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"),
|
||||||
arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."),
|
arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."),
|
||||||
arg_str0(NULL, NULL, "<HEX/ASCII challenge parameter (32b HEX/1..16 chars)>", NULL),
|
arg_str0(NULL, NULL, "<HEX/ASCII challenge parameter (32b HEX/1..16 chars)>", NULL),
|
||||||
|
@ -214,6 +218,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(1);
|
bool APDULogging = arg_get_lit(1);
|
||||||
bool verbose = arg_get_lit(2);
|
bool verbose = arg_get_lit(2);
|
||||||
|
bool verbose2 = arg_get_lit(2) > 1;
|
||||||
bool paramsPlain = arg_get_lit(3);
|
bool paramsPlain = arg_get_lit(3);
|
||||||
|
|
||||||
char fname[250] = {0};
|
char fname[250] = {0};
|
||||||
|
@ -304,7 +309,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
||||||
if (APDULogging)
|
if (APDULogging)
|
||||||
PrintAndLog("---------------------------------------------------------------");
|
PrintAndLog("---------------------------------------------------------------");
|
||||||
PrintAndLog("data len: %d", len);
|
PrintAndLog("data len: %d", len);
|
||||||
if (verbose) {
|
if (verbose2) {
|
||||||
PrintAndLog("--------------data----------------------");
|
PrintAndLog("--------------data----------------------");
|
||||||
dump_buffer((const unsigned char *)buf, len, NULL, 0);
|
dump_buffer((const unsigned char *)buf, len, NULL, 0);
|
||||||
PrintAndLog("--------------data----------------------");
|
PrintAndLog("--------------data----------------------");
|
||||||
|
@ -321,8 +326,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
||||||
|
|
||||||
int derp = 67 + keyHandleLen;
|
int derp = 67 + keyHandleLen;
|
||||||
int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4;
|
int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4;
|
||||||
// needs to decode DER certificate
|
if (verbose2) {
|
||||||
if (verbose) {
|
|
||||||
PrintAndLog("DER certificate[%d]:------------------DER-------------------", derLen);
|
PrintAndLog("DER certificate[%d]:------------------DER-------------------", derLen);
|
||||||
dump_buffer_simple((const unsigned char *)&buf[67 + keyHandleLen], derLen, NULL);
|
dump_buffer_simple((const unsigned char *)&buf[67 + keyHandleLen], derLen, NULL);
|
||||||
PrintAndLog("\n----------------DER---------------------");
|
PrintAndLog("\n----------------DER---------------------");
|
||||||
|
@ -331,7 +335,56 @@ int CmdHFFidoRegister(const char *cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check and print DER certificate
|
// check and print DER certificate
|
||||||
uint8_t public_key[65] = {0};
|
uint8_t public_key[65] = {0};
|
||||||
|
|
||||||
|
// TODO: print DER certificate in DER view
|
||||||
|
|
||||||
|
// load CA's
|
||||||
|
mbedtls_x509_crt cacert;
|
||||||
|
mbedtls_x509_crt_init(&cacert);
|
||||||
|
res = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) additional_ca_pem, additional_ca_pem_len);
|
||||||
|
if (res < 0) {
|
||||||
|
PrintAndLog("ERROR: CA parse certificate returned -0x%x - %s", -res, ecdsa_get_error(res));
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLog("CA load OK. %d skipped", res);
|
||||||
|
|
||||||
|
// load DER certificate from authenticator's data
|
||||||
|
mbedtls_x509_crt cert;
|
||||||
|
mbedtls_x509_crt_init(&cert);
|
||||||
|
res = mbedtls_x509_crt_parse_der(&cert, &buf[67 + keyHandleLen], derLen);
|
||||||
|
if (res) {
|
||||||
|
PrintAndLog("ERROR: DER parse returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get certificate info
|
||||||
|
char linfo[300] = {0};
|
||||||
|
mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert);
|
||||||
|
PrintAndLog("DER certificate info:\n%s", linfo);
|
||||||
|
|
||||||
|
// verify certificate
|
||||||
|
uint32_t verifyflags = 0;
|
||||||
|
memset(linfo, 0x00, sizeof(linfo));
|
||||||
|
|
||||||
|
res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL);
|
||||||
|
if (res) {
|
||||||
|
PrintAndLog("ERROR: DER verify returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags);
|
||||||
|
PrintAndLog("Verification info:\n%s", linfo);
|
||||||
|
|
||||||
|
// get public key
|
||||||
|
res = ecdsa_public_key_from_pk(&cert.pk, public_key, sizeof(public_key));
|
||||||
|
if (res) {
|
||||||
|
PrintAndLog("ERROR: getting public key from certificate 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res));
|
||||||
|
} else {
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLog("Got a public key from certificate.");
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_x509_crt_free(&cert);
|
||||||
|
mbedtls_x509_crt_free(&cacert);
|
||||||
|
|
||||||
// get hash
|
// get hash
|
||||||
int hashp = 1 + 65 + 1 + keyHandleLen + derLen;
|
int hashp = 1 + 65 + 1 + keyHandleLen + derLen;
|
||||||
|
@ -351,8 +404,8 @@ int CmdHFFidoRegister(const char *cmd) {
|
||||||
size_t xbuflen = 0;
|
size_t xbuflen = 0;
|
||||||
res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen,
|
res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen,
|
||||||
"\x00", 1,
|
"\x00", 1,
|
||||||
adata, 32,
|
&data[32], 32, // application parameter
|
||||||
cdata, 32,
|
&data[0], 32, // challenge parameter
|
||||||
&buf[67], keyHandleLen, // keyHandle
|
&buf[67], keyHandleLen, // keyHandle
|
||||||
&buf[1], 65, // user public key
|
&buf[1], 65, // user public key
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <mbedtls/asn1.h>
|
#include <mbedtls/asn1.h>
|
||||||
#include <mbedtls/aes.h>
|
#include <mbedtls/aes.h>
|
||||||
#include <mbedtls/cmac.h>
|
#include <mbedtls/cmac.h>
|
||||||
|
#include <mbedtls/pk.h>
|
||||||
#include <mbedtls/ecdsa.h>
|
#include <mbedtls/ecdsa.h>
|
||||||
#include <mbedtls/sha256.h>
|
#include <mbedtls/sha256.h>
|
||||||
#include <mbedtls/ctr_drbg.h>
|
#include <mbedtls/ctr_drbg.h>
|
||||||
|
@ -208,6 +209,31 @@ char *ecdsa_get_error(int ret) {
|
||||||
return retstr;
|
return retstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen) {
|
||||||
|
int res = 0;
|
||||||
|
size_t realkeylen = 0;
|
||||||
|
if (keylen < 65)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
mbedtls_ecdsa_context ctx;
|
||||||
|
mbedtls_ecdsa_init(&ctx);
|
||||||
|
|
||||||
|
res = mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1
|
||||||
|
if (res)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
res = mbedtls_ecdsa_from_keypair(&ctx, mbedtls_pk_ec(*pk) );
|
||||||
|
if (res)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &realkeylen, key, keylen);
|
||||||
|
if (realkeylen != 65)
|
||||||
|
res = 2;
|
||||||
|
exit:
|
||||||
|
mbedtls_ecdsa_free(&ctx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) {
|
int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) {
|
||||||
int res;
|
int res;
|
||||||
*signaturelen = 0;
|
*signaturelen = 0;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <mbedtls/pk.h>
|
||||||
|
|
||||||
extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
|
extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
|
||||||
extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
|
extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
|
||||||
|
@ -23,6 +24,7 @@ extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, in
|
||||||
extern int sha256hash(uint8_t *input, int length, uint8_t *hash);
|
extern int sha256hash(uint8_t *input, int length, uint8_t *hash);
|
||||||
|
|
||||||
extern int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy);
|
extern int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy);
|
||||||
|
extern int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen);
|
||||||
extern int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen);
|
extern int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen);
|
||||||
extern int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen);
|
extern int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen);
|
||||||
extern char *ecdsa_get_error(int ret);
|
extern char *ecdsa_get_error(int ret);
|
||||||
|
|
63
client/fido/additional_ca.c
Normal file
63
client/fido/additional_ca.c
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2018 Merlok
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// CA PEM certificates
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "additional_ca.h"
|
||||||
|
#include "mbedtls/certs.h"
|
||||||
|
|
||||||
|
#define GLOBALSIGN_CA \
|
||||||
|
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||||
|
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n" \
|
||||||
|
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n" \
|
||||||
|
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\r\n" \
|
||||||
|
"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n" \
|
||||||
|
"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\r\n" \
|
||||||
|
"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\r\n" \
|
||||||
|
"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\r\n" \
|
||||||
|
"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\r\n" \
|
||||||
|
"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\r\n" \
|
||||||
|
"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\r\n" \
|
||||||
|
"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\r\n" \
|
||||||
|
"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\r\n" \
|
||||||
|
"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\r\n" \
|
||||||
|
"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\r\n" \
|
||||||
|
"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\r\n" \
|
||||||
|
"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\r\n" \
|
||||||
|
"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\r\n" \
|
||||||
|
"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\r\n" \
|
||||||
|
"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n" \
|
||||||
|
"-----END CERTIFICATE-----\r\n"
|
||||||
|
|
||||||
|
// Name: Yubico U2F Root CA Serial 457200631
|
||||||
|
// Issued: 2014-08-01
|
||||||
|
#define YUBICO_CA \
|
||||||
|
"-----BEGIN CERTIFICATE-----" \
|
||||||
|
"MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ" \
|
||||||
|
"dWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw" \
|
||||||
|
"MDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290" \
|
||||||
|
"IENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK" \
|
||||||
|
"AoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk" \
|
||||||
|
"5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep" \
|
||||||
|
"8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw" \
|
||||||
|
"nebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT" \
|
||||||
|
"9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw" \
|
||||||
|
"LvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ" \
|
||||||
|
"hjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN" \
|
||||||
|
"BgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4" \
|
||||||
|
"MYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt" \
|
||||||
|
"hX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k" \
|
||||||
|
"LVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U" \
|
||||||
|
"sG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc" \
|
||||||
|
"U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==" \
|
||||||
|
"-----END CERTIFICATE-----"
|
||||||
|
|
||||||
|
/* Concatenation of all additional CA certificates in PEM format if available */
|
||||||
|
const char additional_ca_pem[] = YUBICO_CA; ///GLOBALSIGN_CA
|
||||||
|
const size_t additional_ca_pem_len = sizeof(additional_ca_pem);
|
21
client/fido/additional_ca.h
Normal file
21
client/fido/additional_ca.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2018 Merlok
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// CA PEM certificates
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __ADDITIONAL_CA_H__
|
||||||
|
#define __ADDITIONAL_CA_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// Concatenation of all CA certificates in PEM format if available
|
||||||
|
extern const char additional_ca_pem[];
|
||||||
|
extern const size_t additional_ca_pem_len;
|
||||||
|
|
||||||
|
#endif /* __ADDITIONAL_CA_H__ */
|
0
client/obj/fido/.dummy
Normal file
0
client/obj/fido/.dummy
Normal file
|
@ -29,6 +29,7 @@ mbedtls_SOURCES = \
|
||||||
arc4.c \
|
arc4.c \
|
||||||
pk.c \
|
pk.c \
|
||||||
pk_wrap.c \
|
pk_wrap.c \
|
||||||
|
pkwrite.c \
|
||||||
pkcs5.c \
|
pkcs5.c \
|
||||||
pkcs12.c \
|
pkcs12.c \
|
||||||
pkparse.c \
|
pkparse.c \
|
||||||
|
|
517
common/mbedtls/pkwrite.c
Normal file
517
common/mbedtls/pkwrite.c
Normal file
|
@ -0,0 +1,517 @@
|
||||||
|
/*
|
||||||
|
* Public Key layer for writing key files and structures
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||||
|
#include "mbedtls/config.h"
|
||||||
|
#else
|
||||||
|
#include MBEDTLS_CONFIG_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_PK_WRITE_C)
|
||||||
|
|
||||||
|
#include "mbedtls/pk.h"
|
||||||
|
#include "mbedtls/asn1write.h"
|
||||||
|
#include "mbedtls/oid.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_RSA_C)
|
||||||
|
#include "mbedtls/rsa.h"
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_ECP_C)
|
||||||
|
#include "mbedtls/ecp.h"
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_ECDSA_C)
|
||||||
|
#include "mbedtls/ecdsa.h"
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_PEM_WRITE_C)
|
||||||
|
#include "mbedtls/pem.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_PLATFORM_C)
|
||||||
|
#include "mbedtls/platform.h"
|
||||||
|
#else
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define mbedtls_calloc calloc
|
||||||
|
#define mbedtls_free free
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_RSA_C)
|
||||||
|
/*
|
||||||
|
* RSAPublicKey ::= SEQUENCE {
|
||||||
|
* modulus INTEGER, -- n
|
||||||
|
* publicExponent INTEGER -- e
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
|
||||||
|
mbedtls_rsa_context *rsa )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
size_t len = 0;
|
||||||
|
mbedtls_mpi T;
|
||||||
|
|
||||||
|
mbedtls_mpi_init( &T );
|
||||||
|
|
||||||
|
/* Export E */
|
||||||
|
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export N */
|
||||||
|
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
end_of_export:
|
||||||
|
|
||||||
|
mbedtls_mpi_free( &T );
|
||||||
|
if( ret < 0 )
|
||||||
|
return( ret );
|
||||||
|
|
||||||
|
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_CONSTRUCTED |
|
||||||
|
MBEDTLS_ASN1_SEQUENCE ) );
|
||||||
|
|
||||||
|
return( (int) len );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_RSA_C */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_ECP_C)
|
||||||
|
/*
|
||||||
|
* EC public key is an EC point
|
||||||
|
*/
|
||||||
|
static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
|
||||||
|
mbedtls_ecp_keypair *ec )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
size_t len = 0;
|
||||||
|
unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q,
|
||||||
|
MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||||
|
&len, buf, sizeof( buf ) ) ) != 0 )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( *p < start || (size_t)( *p - start ) < len )
|
||||||
|
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||||
|
|
||||||
|
*p -= len;
|
||||||
|
memcpy( *p, buf, len );
|
||||||
|
|
||||||
|
return( (int) len );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ECParameters ::= CHOICE {
|
||||||
|
* namedCurve OBJECT IDENTIFIER
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
static int pk_write_ec_param( unsigned char **p, unsigned char *start,
|
||||||
|
mbedtls_ecp_keypair *ec )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
size_t len = 0;
|
||||||
|
const char *oid;
|
||||||
|
size_t oid_len;
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
|
||||||
|
return( ret );
|
||||||
|
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
|
||||||
|
|
||||||
|
return( (int) len );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_ECP_C */
|
||||||
|
|
||||||
|
int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
|
||||||
|
const mbedtls_pk_context *key )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_RSA_C)
|
||||||
|
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_ECP_C)
|
||||||
|
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
|
||||||
|
|
||||||
|
return( (int) len );
|
||||||
|
}
|
||||||
|
|
||||||
|
int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned char *c;
|
||||||
|
size_t len = 0, par_len = 0, oid_len;
|
||||||
|
const char *oid;
|
||||||
|
|
||||||
|
c = buf + size;
|
||||||
|
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
|
||||||
|
|
||||||
|
if( c - buf < 1 )
|
||||||
|
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||||
|
* algorithm AlgorithmIdentifier,
|
||||||
|
* subjectPublicKey BIT STRING }
|
||||||
|
*/
|
||||||
|
*--c = 0;
|
||||||
|
len += 1;
|
||||||
|
|
||||||
|
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_BIT_STRING ) );
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ),
|
||||||
|
&oid, &oid_len ) ) != 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_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
|
||||||
|
par_len ) );
|
||||||
|
|
||||||
|
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;
|
||||||
|
unsigned char *c = buf + size;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_RSA_C)
|
||||||
|
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
|
||||||
|
{
|
||||||
|
mbedtls_mpi T; /* Temporary holding the exported parameters */
|
||||||
|
mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Export the parameters one after another to avoid simultaneous copies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mbedtls_mpi_init( &T );
|
||||||
|
|
||||||
|
/* Export QP */
|
||||||
|
if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export DQ */
|
||||||
|
if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export DP */
|
||||||
|
if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export Q */
|
||||||
|
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
|
||||||
|
&T, NULL, NULL ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export P */
|
||||||
|
if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,
|
||||||
|
NULL, NULL, NULL ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export D */
|
||||||
|
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
|
||||||
|
NULL, &T, NULL ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export E */
|
||||||
|
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
|
||||||
|
NULL, NULL, &T ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
/* Export N */
|
||||||
|
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,
|
||||||
|
NULL, NULL, NULL ) ) != 0 ||
|
||||||
|
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
|
||||||
|
goto end_of_export;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
end_of_export:
|
||||||
|
|
||||||
|
mbedtls_mpi_free( &T );
|
||||||
|
if( ret < 0 )
|
||||||
|
return( ret );
|
||||||
|
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
|
||||||
|
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 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* MBEDTLS_RSA_C */
|
||||||
|
#if defined(MBEDTLS_ECP_C)
|
||||||
|
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
|
||||||
|
{
|
||||||
|
mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key );
|
||||||
|
size_t pub_len = 0, par_len = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* publicKey */
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
|
||||||
|
|
||||||
|
if( c - buf < 1 )
|
||||||
|
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||||
|
*--c = 0;
|
||||||
|
pub_len += 1;
|
||||||
|
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
|
||||||
|
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf,
|
||||||
|
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) );
|
||||||
|
len += pub_len;
|
||||||
|
|
||||||
|
/* parameters */
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
|
||||||
|
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) );
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf,
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* version */
|
||||||
|
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
|
||||||
|
|
||||||
|
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 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* MBEDTLS_ECP_C */
|
||||||
|
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
|
||||||
|
|
||||||
|
return( (int) len );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_PEM_WRITE_C)
|
||||||
|
|
||||||
|
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
|
||||||
|
#define PEM_END_PUBLIC_KEY "-----END PUBLIC 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"
|
||||||
|
#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Max sizes of key per types. Shown as tag + len (+ content).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_RSA_C)
|
||||||
|
/*
|
||||||
|
* RSA public keys:
|
||||||
|
* SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3
|
||||||
|
* algorithm AlgorithmIdentifier, 1 + 1 (sequence)
|
||||||
|
* + 1 + 1 + 9 (rsa oid)
|
||||||
|
* + 1 + 1 (params null)
|
||||||
|
* subjectPublicKey BIT STRING } 1 + 3 + (1 + below)
|
||||||
|
* RSAPublicKey ::= SEQUENCE { 1 + 3
|
||||||
|
* modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1
|
||||||
|
* publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RSA private keys:
|
||||||
|
* RSAPrivateKey ::= SEQUENCE { 1 + 3
|
||||||
|
* version Version, 1 + 1 + 1
|
||||||
|
* modulus INTEGER, 1 + 3 + MPI_MAX + 1
|
||||||
|
* publicExponent INTEGER, 1 + 3 + MPI_MAX + 1
|
||||||
|
* privateExponent INTEGER, 1 + 3 + MPI_MAX + 1
|
||||||
|
* prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
|
||||||
|
* prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
|
||||||
|
* exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
|
||||||
|
* exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
|
||||||
|
* coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1
|
||||||
|
* otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \
|
||||||
|
MBEDTLS_MPI_MAX_SIZE % 2
|
||||||
|
#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
|
||||||
|
+ 5 * MPI_MAX_SIZE_2
|
||||||
|
|
||||||
|
#else /* MBEDTLS_RSA_C */
|
||||||
|
|
||||||
|
#define RSA_PUB_DER_MAX_BYTES 0
|
||||||
|
#define RSA_PRV_DER_MAX_BYTES 0
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_RSA_C */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_ECP_C)
|
||||||
|
/*
|
||||||
|
* EC public keys:
|
||||||
|
* SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2
|
||||||
|
* algorithm AlgorithmIdentifier, 1 + 1 (sequence)
|
||||||
|
* + 1 + 1 + 7 (ec oid)
|
||||||
|
* + 1 + 1 + 9 (namedCurve oid)
|
||||||
|
* subjectPublicKey BIT STRING 1 + 2 + 1 [1]
|
||||||
|
* + 1 (point format) [1]
|
||||||
|
* + 2 * ECP_MAX (coords) [1]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EC private keys:
|
||||||
|
* ECPrivateKey ::= SEQUENCE { 1 + 2
|
||||||
|
* version INTEGER , 1 + 1 + 1
|
||||||
|
* privateKey OCTET STRING, 1 + 1 + ECP_MAX
|
||||||
|
* parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9)
|
||||||
|
* publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES
|
||||||
|
|
||||||
|
#else /* MBEDTLS_ECP_C */
|
||||||
|
|
||||||
|
#define ECP_PUB_DER_MAX_BYTES 0
|
||||||
|
#define ECP_PRV_DER_MAX_BYTES 0
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_ECP_C */
|
||||||
|
|
||||||
|
#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
|
||||||
|
RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
|
||||||
|
#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
|
||||||
|
|
||||||
|
int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned char output_buf[PUB_DER_MAX_BYTES];
|
||||||
|
size_t olen = 0;
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,
|
||||||
|
sizeof(output_buf) ) ) < 0 )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
|
||||||
|
output_buf + sizeof(output_buf) - ret,
|
||||||
|
ret, buf, size, &olen ) ) != 0 )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned char output_buf[PRV_DER_MAX_BYTES];
|
||||||
|
const char *begin, *end;
|
||||||
|
size_t olen = 0;
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
|
||||||
|
return( ret );
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_RSA_C)
|
||||||
|
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
|
||||||
|
{
|
||||||
|
begin = PEM_BEGIN_PRIVATE_KEY_RSA;
|
||||||
|
end = PEM_END_PRIVATE_KEY_RSA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_ECP_C)
|
||||||
|
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
|
||||||
|
{
|
||||||
|
begin = PEM_BEGIN_PRIVATE_KEY_EC;
|
||||||
|
end = PEM_END_PRIVATE_KEY_EC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_pem_write_buffer( begin, end,
|
||||||
|
output_buf + sizeof(output_buf) - ret,
|
||||||
|
ret, buf, size, &olen ) ) != 0 )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_PEM_WRITE_C */
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_PK_WRITE_C */
|
Loading…
Add table
Add a link
Reference in a new issue