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 \
|
||||
mfkey.c \
|
||||
tea.c \
|
||||
fido/additional_ca.c \
|
||||
polarssl/des.c \
|
||||
crypto/libpcrypto.c\
|
||||
crypto/asn1utils.c\
|
||||
|
|
|
@ -41,6 +41,10 @@
|
|||
#include "cliparser/cliparser.h"
|
||||
#include "crypto/asn1utils.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);
|
||||
|
||||
|
@ -203,7 +207,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
|||
void* argtable[] = {
|
||||
arg_param_begin,
|
||||
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_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),
|
||||
|
@ -214,6 +218,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
|||
|
||||
bool APDULogging = arg_get_lit(1);
|
||||
bool verbose = arg_get_lit(2);
|
||||
bool verbose2 = arg_get_lit(2) > 1;
|
||||
bool paramsPlain = arg_get_lit(3);
|
||||
|
||||
char fname[250] = {0};
|
||||
|
@ -304,7 +309,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
|||
if (APDULogging)
|
||||
PrintAndLog("---------------------------------------------------------------");
|
||||
PrintAndLog("data len: %d", len);
|
||||
if (verbose) {
|
||||
if (verbose2) {
|
||||
PrintAndLog("--------------data----------------------");
|
||||
dump_buffer((const unsigned char *)buf, len, NULL, 0);
|
||||
PrintAndLog("--------------data----------------------");
|
||||
|
@ -321,8 +326,7 @@ int CmdHFFidoRegister(const char *cmd) {
|
|||
|
||||
int derp = 67 + keyHandleLen;
|
||||
int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4;
|
||||
// needs to decode DER certificate
|
||||
if (verbose) {
|
||||
if (verbose2) {
|
||||
PrintAndLog("DER certificate[%d]:------------------DER-------------------", derLen);
|
||||
dump_buffer_simple((const unsigned char *)&buf[67 + keyHandleLen], derLen, NULL);
|
||||
PrintAndLog("\n----------------DER---------------------");
|
||||
|
@ -331,7 +335,56 @@ int CmdHFFidoRegister(const char *cmd) {
|
|||
}
|
||||
|
||||
// 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
|
||||
int hashp = 1 + 65 + 1 + keyHandleLen + derLen;
|
||||
|
@ -351,8 +404,8 @@ int CmdHFFidoRegister(const char *cmd) {
|
|||
size_t xbuflen = 0;
|
||||
res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen,
|
||||
"\x00", 1,
|
||||
adata, 32,
|
||||
cdata, 32,
|
||||
&data[32], 32, // application parameter
|
||||
&data[0], 32, // challenge parameter
|
||||
&buf[67], keyHandleLen, // keyHandle
|
||||
&buf[1], 65, // user public key
|
||||
NULL, 0);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <mbedtls/asn1.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/cmac.h>
|
||||
#include <mbedtls/pk.h>
|
||||
#include <mbedtls/ecdsa.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
|
@ -208,6 +209,31 @@ char *ecdsa_get_error(int ret) {
|
|||
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 res;
|
||||
*signaturelen = 0;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.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_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 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_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen);
|
||||
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 \
|
||||
pk.c \
|
||||
pk_wrap.c \
|
||||
pkwrite.c \
|
||||
pkcs5.c \
|
||||
pkcs12.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