X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/69f98ec91e3fac3155d8e577c7544f7c99cec447..d03fb293bce1b06d49fb9faf5c492a1e2effc24b:/client/emv/crypto_polarssl.c diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c new file mode 100644 index 00000000..760395c4 --- /dev/null +++ b/client/emv/crypto_polarssl.c @@ -0,0 +1,351 @@ +/* + * libopenemv - a library to work with EMV family of smart cards + * Copyright (C) 2015 Dmitry Eremin-Solenikov + * Copyright (C) 2017 Merlok + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "crypto.h" +#include "crypto_backend.h" + +#include +#include +#include + +#include "rsa.h" +#include "sha1.h" + +struct crypto_hash_polarssl { + struct crypto_hash ch; + sha1_context ctx; +}; + +static void crypto_hash_polarssl_close(struct crypto_hash *_ch) +{ + struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch; + + free(ch); +} + +static void crypto_hash_polarssl_write(struct crypto_hash *_ch, const unsigned char *buf, size_t len) +{ + struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch; + + sha1_update(&(ch->ctx), buf, len); +} + +static unsigned char *crypto_hash_polarssl_read(struct crypto_hash *_ch) +{ + struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch; + + static unsigned char sha1sum[20]; + sha1_finish(&(ch->ctx), sha1sum); + return sha1sum; +} + +static size_t crypto_hash_polarssl_get_size(const struct crypto_hash *ch) +{ + if (ch->algo == HASH_SHA_1) + return 20; + else + return 0; +} + +static struct crypto_hash *crypto_hash_polarssl_open(enum crypto_algo_hash hash) +{ + if (hash != HASH_SHA_1) + return NULL; + + struct crypto_hash_polarssl *ch = malloc(sizeof(*ch)); + + sha1_starts(&(ch->ctx)); + + ch->ch.write = crypto_hash_polarssl_write; + ch->ch.read = crypto_hash_polarssl_read; + ch->ch.close = crypto_hash_polarssl_close; + ch->ch.get_size = crypto_hash_polarssl_get_size; + + return &ch->ch; +} + +struct crypto_pk_polarssl { + struct crypto_pk cp; + rsa_context ctx; +}; + +static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl) +{ + struct crypto_pk_polarssl *cp = malloc(sizeof(*cp)); + memset(cp, 0x00, sizeof(*cp)); + + char *mod = va_arg(vl, char *); // N + int modlen = va_arg(vl, size_t); + char *exp = va_arg(vl, char *); // E + int explen = va_arg(vl, size_t); + + rsa_init(&cp->ctx, RSA_PKCS_V15, 0); + + cp->ctx.len = modlen; // size(N) in bytes + mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); + mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); + + int res = rsa_check_pubkey(&cp->ctx); + if(res != 0) { + fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); + + return NULL; + } + + return &cp->cp; +} + +static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) +{ + struct crypto_pk_polarssl *cp = malloc(sizeof(*cp)); + memset(cp, 0x00, sizeof(*cp)); + char *mod = va_arg(vl, char *); + int modlen = va_arg(vl, size_t); + char *exp = va_arg(vl, char *); + int explen = va_arg(vl, size_t); + char *d = va_arg(vl, char *); + int dlen = va_arg(vl, size_t); + char *p = va_arg(vl, char *); + int plen = va_arg(vl, size_t); + char *q = va_arg(vl, char *); + int qlen = va_arg(vl, size_t); + char *dp = va_arg(vl, char *); + int dplen = va_arg(vl, size_t); + char *dq = va_arg(vl, char *); + int dqlen = va_arg(vl, size_t); + // calc QP via Q and P +// char *inv = va_arg(vl, char *); +// int invlen = va_arg(vl, size_t); + + rsa_init(&cp->ctx, RSA_PKCS_V15, 0); + + cp->ctx.len = modlen; // size(N) in bytes + mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); + mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); + + mpi_read_binary(&cp->ctx.D, (const unsigned char *)d, dlen); + mpi_read_binary(&cp->ctx.P, (const unsigned char *)p, plen); + mpi_read_binary(&cp->ctx.Q, (const unsigned char *)q, qlen); + mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen); + mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen); + mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P); + + int res = rsa_check_privkey(&cp->ctx); + if(res != 0) { + fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); + return NULL; + } + + return &cp->cp; +} + +static int myrand(void *rng_state, unsigned char *output, size_t len) { + size_t i; + + if(rng_state != NULL) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); + + return 0; +} + + +static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl) +{ + struct crypto_pk_polarssl *cp = malloc(sizeof(*cp)); + memset(cp, 0x00, sizeof(*cp)); + + int transient = va_arg(vl, int); + unsigned int nbits = va_arg(vl, unsigned int); + unsigned int exp = va_arg(vl, unsigned int); + + if (transient) { + } + + int res = rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp); + if (res) { + fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits); + return NULL; + } + + return &cp->cp; +} + +static void crypto_pk_polarssl_close(struct crypto_pk *_cp) +{ + struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; + + rsa_free(&cp->ctx); + free(cp); +} + +static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, const unsigned char *buf, size_t len, size_t *clen) +{ + struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; + int res; + unsigned char *result; + + *clen = 0; + size_t keylen = mpi_size(&cp->ctx.N); + + result = malloc(keylen); + if (!result) { + printf("RSA encrypt failed. Can't allocate result memory.\n"); + return NULL; + } + + res = rsa_public(&cp->ctx, buf, result); + if(res) { + printf("RSA encrypt failed. Error: %x data len: %d key len: %d\n", res * -1, len, keylen); + return NULL; + } + + *clen = keylen; + + return result; +} + +static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, const unsigned char *buf, size_t len, size_t *clen) +{ + struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; + int res; + unsigned char *result; + + *clen = 0; + size_t keylen = mpi_size(&cp->ctx.N); + + result = malloc(keylen); + if (!result) { + printf("RSA encrypt failed. Can't allocate result memory.\n"); + return NULL; + } + + res = rsa_private(&cp->ctx, buf, result); // CHECK??? + if(res) { + printf("RSA decrypt failed. Error: %x data len: %d key len: %d\n", res * -1, len, keylen); + return NULL; + } + + *clen = keylen; + + return result; +} + +static size_t crypto_pk_polarssl_get_nbits(const struct crypto_pk *_cp) +{ + struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; + + return cp->ctx.len * 8; +return 0; +} + +static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_cp, unsigned param, size_t *plen) +{ + struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; + unsigned char *result = NULL; + switch(param){ + // mod + case 0: + *plen = mpi_size(&cp->ctx.N); + result = malloc(*plen); + memset(result, 0x00, *plen); + mpi_write_binary(&cp->ctx.N, result, *plen); + break; + // exp + case 1: + *plen = mpi_size(&cp->ctx.E); + result = malloc(*plen); + memset(result, 0x00, *plen); + mpi_write_binary(&cp->ctx.E, result, *plen); + break; + default: + printf("Error get parameter. Param=%d", param); + break; + } + + return result; +} + +static struct crypto_pk *crypto_pk_polarssl_open(enum crypto_algo_pk pk, va_list vl) +{ + struct crypto_pk *cp; + + if (pk == PK_RSA) + cp = crypto_pk_polarssl_open_rsa(vl); + else + return NULL; + + cp->close = crypto_pk_polarssl_close; + cp->encrypt = crypto_pk_polarssl_encrypt; + cp->get_parameter = crypto_pk_polarssl_get_parameter; + cp->get_nbits = crypto_pk_polarssl_get_nbits; + + return cp; +} + +static struct crypto_pk *crypto_pk_polarssl_open_priv(enum crypto_algo_pk pk, va_list vl) +{ + struct crypto_pk *cp; + + if (pk == PK_RSA) + cp = crypto_pk_polarssl_open_priv_rsa(vl); + else + return NULL; + + cp->close = crypto_pk_polarssl_close; + cp->encrypt = crypto_pk_polarssl_encrypt; + cp->decrypt = crypto_pk_polarssl_decrypt; + cp->get_parameter = crypto_pk_polarssl_get_parameter; + cp->get_nbits = crypto_pk_polarssl_get_nbits; + + return cp; +} + +static struct crypto_pk *crypto_pk_polarssl_genkey(enum crypto_algo_pk pk, va_list vl) +{ + struct crypto_pk *cp; + + if (pk == PK_RSA) + cp = crypto_pk_polarssl_genkey_rsa(vl); + else + return NULL; + + cp->close = crypto_pk_polarssl_close; + cp->encrypt = crypto_pk_polarssl_encrypt; + cp->decrypt = crypto_pk_polarssl_decrypt; + cp->get_parameter = crypto_pk_polarssl_get_parameter; + cp->get_nbits = crypto_pk_polarssl_get_nbits; + + return cp; +} + +static struct crypto_backend crypto_polarssl_backend = { + .hash_open = crypto_hash_polarssl_open, + .pk_open = crypto_pk_polarssl_open, + .pk_open_priv = crypto_pk_polarssl_open_priv, + .pk_genkey = crypto_pk_polarssl_genkey, +}; + +struct crypto_backend *crypto_polarssl_init(void) +{ + return &crypto_polarssl_backend; +}