diff --git a/npa/src/Makefile.am b/npa/src/Makefile.am index 7f787e4..b72569d 100644 --- a/npa/src/Makefile.am +++ b/npa/src/Makefile.am @@ -2,7 +2,7 @@ EXTRA_DIST = $(shell find $(top_srcdir)/src/opensc -path '*/.svn' -prune -o -typ AM_CPPFLAGS = -I$(top_srcdir)/src/npa -I$(top_srcdir)/src/opensc/src -libnpa_la_SOURCES = sm.c scutil.c npa.c npa_lib.c +libnpa_la_SOURCES = sm.c scutil.c npa.c libnpa_la_LIBADD = $(OPENSSL_LIBS) $(OPENSC_LIBS) libnpa_la_CFLAGS = $(OPENSSL_CFLAGS) @@ -21,5 +21,4 @@ noinst_HEADERS = \ nobase_include_HEADERS = \ npa/sm.h \ npa/npa.h \ - npa/scutil.h \ - npa/npa_lib.h + npa/scutil.h diff --git a/npa/src/npa-tool.c b/npa/src/npa-tool.c index 5f6c510..555067f 100644 --- a/npa/src/npa-tool.c +++ b/npa/src/npa-tool.c @@ -541,8 +541,8 @@ main (int argc, char **argv) } err: - npa_sm_ctx_clear_free(sctx.cipher_ctx); - npa_sm_ctx_clear_free(tmpctx.cipher_ctx); + sm_ctx_clear_free(&sctx); + sm_ctx_clear_free(&tmpctx); if (pace_output.ef_cardaccess) free(pace_output.ef_cardaccess); if (pace_output.recent_car) diff --git a/npa/src/npa.c b/npa/src/npa.c index 3235021..5fe3614 100644 --- a/npa/src/npa.c +++ b/npa/src/npa.c @@ -148,6 +148,18 @@ IMPLEMENT_ASN1_FUNCTIONS(NPA_GEN_AUTH_R) const size_t maxresp = SC_MAX_APDU_BUFFER_SIZE - 2; +/** NPA secure messaging context */ +struct npa_sm_ctx { + /** Send sequence counter */ + BIGNUM *ssc; + /** Key for message authentication code */ + const BUF_MEM *key_mac; + /** Key for encryption and decryption */ + const BUF_MEM *key_enc; + /** PACE context */ + PACE_CTX *ctx; +}; + static int npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx, const u8 *data, size_t datalen, u8 **enc); static int npa_sm_decrypt(sc_card_t *card, const struct sm_ctx *ctx, @@ -161,11 +173,40 @@ static int npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx, sc_apdu_t *apdu); static int npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx, sc_apdu_t *sm_apdu); +static void npa_sm_clear_free(const struct sm_ctx *ctx); static int increment_ssc(struct npa_sm_ctx *psmctx); static int decrement_ssc(struct npa_sm_ctx *psmctx); static int reset_ssc(struct npa_sm_ctx *psmctx); +static struct npa_sm_ctx * +npa_sm_ctx_create(const BUF_MEM *key_mac, + const BUF_MEM *key_enc, PACE_CTX *ctx) +{ + struct npa_sm_ctx *out = malloc(sizeof *out); + if (!out) + goto err; + + out->ssc = BN_new(); + if (!out->ssc || reset_ssc(out) < 0) + goto err; + + out->key_enc = key_enc; + out->key_mac = key_mac; + out->ctx = ctx; + + + return out; + +err: + if (out) { + if (out->ssc) + BN_clear_free(out->ssc); + free(out); + } + return NULL; +} + int GetReadersPACECapabilities(u8 *bitmap) { @@ -1227,22 +1268,18 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card, bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID PCD", pace_output->id_pcd, pace_output->id_pcd_length); - sctx->authentication_ctx = npa_sm_ctx_create(k_mac, - k_enc, pctx); - if (!sctx->authentication_ctx) { + sctx->priv_data = npa_sm_ctx_create(k_mac, k_enc, pctx); + if (!sctx->priv_data) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } - r = reset_ssc(sctx->authentication_ctx); - if (r < 0) - goto err; - sctx->cipher_ctx = sctx->authentication_ctx; sctx->authenticate = npa_sm_authenticate; sctx->encrypt = npa_sm_encrypt; sctx->decrypt = npa_sm_decrypt; sctx->verify_authentication = npa_sm_verify_authentication; sctx->pre_transmit = npa_sm_pre_transmit; sctx->post_transmit = npa_sm_post_transmit; + sctx->clear_free = npa_sm_clear_free; sctx->padding_indicator = SM_ISO_PADDING; sctx->block_length = EVP_CIPHER_block_size(pctx->cipher); sctx->active = 1; @@ -1298,8 +1335,8 @@ err: } if (pctx) PACE_CTX_clear_free(pctx); - if (sctx->authentication_ctx) - npa_sm_ctx_free(sctx->authentication_ctx); + if (sctx->priv_data) + npa_sm_clear_free(sctx->priv_data); } return r; @@ -1366,11 +1403,11 @@ npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx, u8 *p = NULL; int r; - if (!ctx || !enc || !ctx->cipher_ctx) { + if (!ctx || !enc || !ctx->priv_data) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } - struct npa_sm_ctx *psmctx = ctx->cipher_ctx; + struct npa_sm_ctx *psmctx = ctx->priv_data; databuf = BUF_MEM_create_init(data, datalen); encbuf = PACE_encrypt(psmctx->ctx, psmctx->ssc, psmctx->key_enc, databuf); @@ -1410,11 +1447,11 @@ npa_sm_decrypt(sc_card_t *card, const struct sm_ctx *ctx, u8 *p = NULL; int r; - if (!ctx || !enc || !ctx->cipher_ctx || !data) { + if (!ctx || !enc || !ctx->priv_data || !data) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } - struct npa_sm_ctx *psmctx = ctx->cipher_ctx; + struct npa_sm_ctx *psmctx = ctx->priv_data; encbuf = BUF_MEM_create_init(enc, enclen); databuf = PACE_decrypt(psmctx->ctx, psmctx->ssc, psmctx->key_enc, encbuf); @@ -1454,11 +1491,11 @@ npa_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx, u8 *p = NULL, *ssc = NULL; int r; - if (!ctx || !ctx->cipher_ctx || !macdata) { + if (!ctx || !ctx->priv_data || !macdata) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } - struct npa_sm_ctx *psmctx = ctx->cipher_ctx; + struct npa_sm_ctx *psmctx = ctx->priv_data; macbuf = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac, data, datalen); @@ -1498,11 +1535,11 @@ npa_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx, char *p; BUF_MEM *my_mac = NULL; - if (!ctx || !ctx->cipher_ctx) { + if (!ctx || !ctx->priv_data) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } - struct npa_sm_ctx *psmctx = ctx->cipher_ctx; + struct npa_sm_ctx *psmctx = ctx->priv_data; my_mac = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac, macdata, macdatalen); @@ -1538,12 +1575,33 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx, sc_apdu_t *apdu) { SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, - increment_ssc(ctx->cipher_ctx)); + increment_ssc(ctx->priv_data)); } -static int npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx, +static int +npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx, sc_apdu_t *sm_apdu) { SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, - increment_ssc(ctx->cipher_ctx)); + increment_ssc(ctx->priv_data)); +} + +static void +npa_sm_clear_free(const struct sm_ctx *ctx) +{ + if (ctx) { + struct npa_sm_ctx *psmctx = ctx->priv_data; + if (psmctx->key_mac) { + OPENSSL_cleanse(psmctx->key_mac->data, psmctx->key_mac->max); + BUF_MEM_free((BUF_MEM *) psmctx->key_mac); + } + if (psmctx->key_enc) { + OPENSSL_cleanse(psmctx->key_enc->data, psmctx->key_enc->max); + BUF_MEM_free((BUF_MEM *) psmctx->key_enc); + } + PACE_CTX_clear_free(psmctx->ctx); + if (psmctx->ssc) + BN_clear_free(psmctx->ssc); + free(psmctx); + } } diff --git a/npa/src/npa/npa.h b/npa/src/npa/npa.h index f4af1bf..9c10350 100644 --- a/npa/src/npa/npa.h +++ b/npa/src/npa/npa.h @@ -22,7 +22,6 @@ #ifndef _CCID_NPA_H #define _CCID_NPA_H -#include #include #include #include diff --git a/npa/src/npa/npa_lib.h b/npa/src/npa/npa_lib.h deleted file mode 100644 index 8c466fa..0000000 --- a/npa/src/npa/npa_lib.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010 Frank Morgner - * - * This file is part of ccid. - * - * ccid 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 3 of the License, or (at your option) any later - * version. - * - * ccid 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 - * ccid. If not, see . - */ -/** - * @file - */ -#ifndef _CCID_NPA_LIB_H -#define _CCID_NPA_LIB_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** NPA secure messaging context */ -struct npa_sm_ctx { - /** Send sequence counter */ - BIGNUM *ssc; - /** Key for message authentication code */ - const BUF_MEM *key_mac; - /** Key for encryption and decryption */ - const BUF_MEM *key_enc; - /** PACE context */ - PACE_CTX *ctx; -}; - - -/** - * @brief Creates a NPA SM object - * - * @param[in] key_mac Key for message authentication code - * @param[in] key_enc Key for encryption and decryption - * @param[in] ctx NPA context - * - * @return Initialized NPA SM object or NULL, if an error occurred - */ -struct npa_sm_ctx * npa_sm_ctx_create(const BUF_MEM *key_mac, - const BUF_MEM *key_enc, PACE_CTX *ctx); - -/** - * @brief Frees a NPA SM object - * - * Frees memory allocated for \a ctx and its send sequence counter - * - * @param[in] ctx object to be freed - */ -void npa_sm_ctx_free(struct npa_sm_ctx *ctx); - -/** - * @brief Frees a NPA SM object and all its components - * - * Frees memory allocated for \a ctx and its send sequence counter, keys and PACE context - * - * @param[in] ctx object to be freed - */ -void npa_sm_ctx_clear_free(struct npa_sm_ctx *ctx); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/npa/src/npa/sm.h b/npa/src/npa/sm.h index c174d95..0bab594 100644 --- a/npa/src/npa/sm.h +++ b/npa/src/npa/sm.h @@ -38,13 +38,14 @@ struct sm_ctx { /** 1 if secure messaging is activated, 0 otherwise */ unsigned char active; + /** data of the specific crypto implementation */ + void *priv_data; + /** Padding-content indicator byte (ISO 7816-4 Table 30) */ u8 padding_indicator; /** Pad to this block length */ size_t block_length; - /** Authentication context for the specific authentication implementation */ - void *authentication_ctx; /** Call back function for authentication of data */ int (*authenticate)(sc_card_t *card, const struct sm_ctx *ctx, const u8 *data, size_t datalen, u8 **outdata); @@ -53,8 +54,6 @@ struct sm_ctx { const u8 *mac, size_t maclen, const u8 *macdata, size_t macdatalen); - /** Cipher context for the specific cipher implementation */ - void *cipher_ctx; /** Call back function for encryption of data */ int (*encrypt)(sc_card_t *card, const struct sm_ctx *ctx, const u8 *data, size_t datalen, u8 **enc); @@ -68,6 +67,9 @@ struct sm_ctx { /** Call back function for actions before decryption and decoding of \a sm_apdu */ int (*post_transmit)(sc_card_t *card, const struct sm_ctx *ctx, sc_apdu_t *sm_apdu); + + /** Clears and frees private data */ + void (*clear_free)(const struct sm_ctx *ctx); }; /** @@ -92,6 +94,15 @@ struct sm_ctx { int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card, sc_apdu_t *apdu); +/** + * @brief Clears and frees private data of the SM context + * + * Calls \a sctx->clear_free + * + * @param[in] sctx (optional) + */ +void sm_ctx_clear_free(const struct sm_ctx *sctx); + #ifdef __cplusplus } #endif diff --git a/npa/src/npa_lib.c b/npa/src/npa_lib.c deleted file mode 100644 index 3664d2b..0000000 --- a/npa/src/npa_lib.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010 Frank Morgner - * - * This file is part of ccid. - * - * ccid 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 3 of the License, or (at your option) any later - * version. - * - * ccid 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 - * ccid. If not, see . - */ -#include "npa_lib.h" -#include -#include - -struct npa_sm_ctx * -npa_sm_ctx_create(const BUF_MEM *key_mac, - const BUF_MEM *key_enc, PACE_CTX *ctx) -{ - struct npa_sm_ctx *out = malloc(sizeof *out); - if (!out) - return NULL; - - out->ssc = BN_new(); - if (!out->ssc) { - free(out); - return NULL; - } - - out->key_enc = key_enc; - out->key_mac = key_mac; - out->ctx = ctx; - - return out; -} - -void -npa_sm_ctx_free(struct npa_sm_ctx *ctx) -{ - if (ctx) { - if (ctx->ssc) - BN_clear_free(ctx->ssc); - free(ctx); - } -} - -void -npa_sm_ctx_clear_free(struct npa_sm_ctx *ctx) -{ - if (ctx) { - if (ctx->key_mac) { - OPENSSL_cleanse(ctx->key_mac->data, ctx->key_mac->max); - BUF_MEM_free((BUF_MEM *) ctx->key_mac); - } - if (ctx->key_enc) { - OPENSSL_cleanse(ctx->key_enc->data, ctx->key_enc->max); - BUF_MEM_free((BUF_MEM *) ctx->key_enc); - } - PACE_CTX_clear_free(ctx->ctx); - npa_sm_ctx_free(ctx); - } -} diff --git a/npa/src/sm.c b/npa/src/sm.c index c2faae6..e651306 100644 --- a/npa/src/sm.c +++ b/npa/src/sm.c @@ -605,3 +605,9 @@ int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card, return SC_SUCCESS; } + +void sm_ctx_clear_free(const struct sm_ctx *sctx) +{ + if (sctx && sctx->clear_free) + sctx->clear_free(sctx); +}