- Added an untested SM implementation, currently only with encryption
- Added utils from OpenPACE git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@51 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -25,10 +25,10 @@ TARGETS = ccid
|
||||
all: $(TARGETS)
|
||||
|
||||
|
||||
ccid: ccid.h ccid.c pace.h pace.c apdu.h apdu.c usbstring.c usbstring.h usb.c
|
||||
ccid: ccid.h ccid.c pace.h pace.c sm.c sm.h utils.h utils.c apdu.h apdu.c usbstring.c usbstring.h usb.c
|
||||
$(CC) $(LIBPCSCLITE_CFLAGS) $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) \
|
||||
$(PTHREAD_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) \
|
||||
usbstring.c ccid.c pace.c apdu.c usb.c -o $@
|
||||
usbstring.c ccid.c pace.c sm.c utils.c apdu.c usb.c -o $@
|
||||
|
||||
|
||||
install: $(TARGETS) installdirs
|
||||
|
||||
293
ccid/sm.c
Normal file
293
ccid/sm.c
Normal file
@@ -0,0 +1,293 @@
|
||||
#include "sm.h"
|
||||
#include "utils.h"
|
||||
#include <opensc/asn1.h>
|
||||
#include <opensc/log.h>
|
||||
#include <string.h>
|
||||
|
||||
static const struct sc_asn1_entry c_sm_capdu[] = {
|
||||
{ "Padding-content indicator followed by cryptogram",
|
||||
SC_ASN1_INTEGER , 0x87, SC_ASN1_OPTIONAL|SC_ASN1_UNSIGNED, NULL, NULL },
|
||||
{ "Protected Le",
|
||||
SC_ASN1_INTEGER , 0x97, SC_ASN1_OPTIONAL|SC_ASN1_UNSIGNED, NULL, NULL },
|
||||
{ "Cryptographic Checksum",
|
||||
SC_ASN1_OCTET_STRING, 0x8E, 0, NULL, NULL },
|
||||
{ NULL , 0 , 0 , 0 , NULL , NULL }
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_sm_rapdu[] = {
|
||||
{ "Padding-content indicator followed by cryptogram" ,
|
||||
SC_ASN1_INTEGER , 0x87, SC_ASN1_OPTIONAL|SC_ASN1_UNSIGNED, NULL, NULL },
|
||||
{ "Processing Status",
|
||||
SC_ASN1_INTEGER , 0x99, SC_ASN1_OPTIONAL|SC_ASN1_UNSIGNED, NULL, NULL },
|
||||
{ "Cryptographic Checksum",
|
||||
SC_ASN1_OCTET_STRING, 0x8E, 0, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
BUF_MEM *add_padding(const struct sm_ctx *ctx, const char *data, size_t datalen)
|
||||
{
|
||||
BUF_MEM *tmp = BUF_MEM_create_init(data, datalen);
|
||||
BUF_MEM *padded = NULL;
|
||||
|
||||
switch (ctx->padding_indicator) {
|
||||
case SM_NO_PADDING:
|
||||
padded = tmp;
|
||||
tmp = NULL;
|
||||
break;
|
||||
case SM_ISO_PADDING:
|
||||
padded = add_iso_pad(tmp, EVP_CIPHER_block_size(ctx->cipher));
|
||||
if (tmp) {
|
||||
OPENSSL_cleanse(tmp->data, tmp->max);
|
||||
BUF_MEM_free(tmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return padded;
|
||||
}
|
||||
|
||||
u8 * format_le(size_t le_len, size_t le, struct sc_asn1_entry *le_entry)
|
||||
{
|
||||
u8 * lebuf = malloc(le_len);
|
||||
if (lebuf) {
|
||||
switch (le_len) {
|
||||
case 1:
|
||||
lebuf[0] = le;
|
||||
break;
|
||||
case 2:
|
||||
lebuf[0] = htons(le) >> 8;
|
||||
lebuf[1] = htons(le) & 0xff;
|
||||
break;
|
||||
case 3:
|
||||
lebuf[0] = 0x00;
|
||||
lebuf[1] = htons(le) >> 8;
|
||||
lebuf[2] = htons(le) & 0xff;
|
||||
break;
|
||||
default:
|
||||
free(lebuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sc_format_asn1_entry(le_entry, lebuf, &le_len, SC_ASN1_PRESENT);
|
||||
}
|
||||
|
||||
return lebuf;
|
||||
}
|
||||
|
||||
BUF_MEM * prefix_buf(u8 prefix, BUF_MEM *buf)
|
||||
{
|
||||
if (!buf) return NULL;
|
||||
BUF_MEM *cat = BUF_MEM_create(buf->length + 1);
|
||||
if (cat) {
|
||||
cat->data[0] = prefix;
|
||||
memcpy(cat->data + 1, buf->data, buf->length);
|
||||
cat->length = buf->length + 1;
|
||||
}
|
||||
return cat;
|
||||
}
|
||||
|
||||
BUF_MEM * format_data(const struct sm_ctx *ctx, const u8 *data, size_t datalen,
|
||||
struct sc_asn1_entry *formatted_encrypted_data_entry)
|
||||
{
|
||||
BUF_MEM *pad_data = add_padding(ctx, (char *) data, datalen);
|
||||
BUF_MEM *enc_data = cipher(ctx->cipher_ctx, ctx->cipher,
|
||||
ctx->cipher_engine, ctx->key_enc, ctx->iv, 1, pad_data, 1);
|
||||
|
||||
if (pad_data) {
|
||||
OPENSSL_cleanse(pad_data->data, pad_data->max);
|
||||
BUF_MEM_free(pad_data);
|
||||
}
|
||||
|
||||
BUF_MEM *indicator_encdata = prefix_buf(ctx->padding_indicator, enc_data);
|
||||
|
||||
if (enc_data) {
|
||||
BUF_MEM_free(enc_data);
|
||||
}
|
||||
|
||||
if (indicator_encdata)
|
||||
sc_format_asn1_entry(formatted_encrypted_data_entry,
|
||||
indicator_encdata->data, &(indicator_encdata->length),
|
||||
SC_ASN1_PRESENT);
|
||||
return indicator_encdata;
|
||||
}
|
||||
|
||||
int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card, sc_apdu_t *apdu,
|
||||
sc_apdu_t *sm_apdu)
|
||||
{
|
||||
struct sc_asn1_entry sm_capdu[4];
|
||||
u8 *le = NULL;
|
||||
size_t oldlen;
|
||||
BUF_MEM *formatted_data = NULL, *sm_data = NULL,
|
||||
*mac_data = NULL, *mac = NULL, *tmp = NULL;
|
||||
char head[4];
|
||||
int r;
|
||||
|
||||
if (!apdu || !ctx || !card || !card->slot || !sm_apdu) {
|
||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
sc_copy_asn1_entry(c_sm_capdu, sm_capdu);
|
||||
|
||||
head[0] = apdu->cla;
|
||||
head[1] = apdu->ins;
|
||||
head[2] = apdu->p1;
|
||||
head[3] = apdu->p2;
|
||||
mac_data = add_padding(ctx, head, sizeof head);
|
||||
if (!mac_data) {
|
||||
r = SC_ERROR_WRONG_PADDING;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
/* get asn1 encoding of le and padding indicator depending on the case of
|
||||
* the unsecure command */
|
||||
switch (apdu->cse) {
|
||||
case SC_APDU_CASE_1:
|
||||
break;
|
||||
case SC_APDU_CASE_2_SHORT:
|
||||
le = format_le(1, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case SC_APDU_CASE_2_EXT:
|
||||
if (card->slot->active_protocol == SC_PROTO_T0) {
|
||||
/* T0 extended APDUs look just like short APDUs */
|
||||
le = format_le(1, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* in case of T1 always use 3 bytes for length */
|
||||
le = format_le(3, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SC_APDU_CASE_3_SHORT:
|
||||
case SC_APDU_CASE_3_EXT:
|
||||
formatted_data = format_data(ctx, apdu->data, apdu->datalen,
|
||||
sm_capdu + 0);
|
||||
if (!formatted_data) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case SC_APDU_CASE_4_SHORT:
|
||||
/* in case of T0 no Le byte is added */
|
||||
if (card->slot->active_protocol != SC_PROTO_T0) {
|
||||
le = format_le(1, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
formatted_data = format_data(ctx, apdu->data, apdu->datalen,
|
||||
sm_capdu + 0);
|
||||
if (!formatted_data) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case SC_APDU_CASE_4_EXT:
|
||||
if (card->slot->active_protocol == SC_PROTO_T0) {
|
||||
/* again a T0 extended case 4 APDU looks just
|
||||
* like a short APDU, the additional data is
|
||||
* transferred using ENVELOPE and GET RESPONSE */
|
||||
} else {
|
||||
/* only 2 bytes are use to specify the length of the
|
||||
* expected data */
|
||||
le = format_le(2, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
formatted_data = format_data(ctx, apdu->data, apdu->datalen,
|
||||
sm_capdu + 0);
|
||||
if (!formatted_data) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
tmp = BUF_MEM_new();
|
||||
if (!tmp) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
r = sc_asn1_encode(card->ctx, sm_capdu, (u8 **) &tmp->data, &tmp->length);
|
||||
if (r < 0) {
|
||||
goto err;
|
||||
}
|
||||
oldlen = mac_data->length;
|
||||
BUF_MEM_grow(mac_data, oldlen + tmp->length);
|
||||
memcpy(mac_data->data + oldlen, tmp->data, tmp->length);
|
||||
BUF_MEM_free(tmp);
|
||||
tmp = add_padding(ctx, mac_data->data, mac_data->length);
|
||||
BUF_MEM_free(mac_data);
|
||||
mac_data = hash(ctx->md, ctx->md_ctx, ctx->md_engine, tmp);
|
||||
mac = cipher(ctx->cipher_ctx, ctx->cipher, ctx->cipher_engine,
|
||||
ctx->key_mac, ctx->iv, 1, mac_data, 1);
|
||||
if (!mac) {
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
sc_format_asn1_entry(sm_capdu + 2, mac->data, &(mac->length),
|
||||
SC_ASN1_PRESENT);
|
||||
|
||||
|
||||
/* format SM apdu */
|
||||
BUF_MEM_free(sm_data);
|
||||
sm_data = BUF_MEM_new();
|
||||
if (!sm_data) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
r = sc_asn1_encode(card->ctx, sm_capdu, (u8 **) &sm_data->data, &sm_data->length);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
memset(sm_apdu, 0, sizeof *sm_apdu);
|
||||
sm_apdu->cla = apdu->cla;
|
||||
sm_apdu->ins = apdu->ins;
|
||||
sm_apdu->p1 = apdu->p1;
|
||||
sm_apdu->p2 = apdu->p2;
|
||||
sm_apdu->data = (u8 *) sm_data->data;
|
||||
sm_apdu->lc = sm_data->length;
|
||||
sm_apdu->le = 0;
|
||||
sm_apdu->cse = SC_APDU_CASE_4;
|
||||
|
||||
err:
|
||||
if (formatted_data) {
|
||||
BUF_MEM_free(formatted_data);
|
||||
}
|
||||
if (tmp) {
|
||||
BUF_MEM_free(tmp);
|
||||
}
|
||||
if (mac_data) {
|
||||
BUF_MEM_free(mac_data);
|
||||
}
|
||||
if (mac) {
|
||||
BUF_MEM_free(mac);
|
||||
}
|
||||
if (le) {
|
||||
free(le);
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
|
||||
}
|
||||
25
ccid/sm.h
Normal file
25
ccid/sm.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <opensc/opensc.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#define SM_ISO_PADDING 0x01
|
||||
#define SM_NO_PADDING 0x02
|
||||
|
||||
struct sm_ctx {
|
||||
u8 padding_indicator;
|
||||
u8 *key_mac;
|
||||
size_t key_mac_len;
|
||||
u8 *key_enc;
|
||||
size_t key_enc_len;
|
||||
|
||||
const EVP_CIPHER *cipher;
|
||||
EVP_CIPHER_CTX *cipher_ctx;
|
||||
ENGINE *cipher_engine;
|
||||
unsigned char *iv;
|
||||
|
||||
const EVP_MD * md;
|
||||
EVP_MD_CTX * md_ctx;
|
||||
ENGINE *md_engine;
|
||||
};
|
||||
|
||||
int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card, sc_apdu_t *apdu,
|
||||
sc_apdu_t *sm_apdu);
|
||||
279
ccid/utils.c
Normal file
279
ccid/utils.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/**
|
||||
* @date 2009-11-30
|
||||
* @version 0.1
|
||||
* @author Frank Morgner <morgner@informatik.hu-berlin.de>
|
||||
* @author Dominik Oepen <oepen@informatik.hu-berlin.de>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/err.h>
|
||||
#include "utils.h"
|
||||
|
||||
BUF_MEM *
|
||||
hash(const EVP_MD * md, EVP_MD_CTX * ctx, ENGINE * impl, const BUF_MEM * in)
|
||||
{
|
||||
BUF_MEM * out = NULL;
|
||||
EVP_MD_CTX * tmp_ctx = NULL;
|
||||
unsigned int tmp_len;
|
||||
|
||||
if (!md || !in)
|
||||
goto err;
|
||||
|
||||
if (ctx)
|
||||
tmp_ctx = ctx;
|
||||
else {
|
||||
tmp_ctx = EVP_MD_CTX_create();
|
||||
if (!tmp_ctx)
|
||||
goto err;
|
||||
}
|
||||
|
||||
tmp_len = EVP_MD_size(md);
|
||||
out = BUF_MEM_create(tmp_len);
|
||||
if (!out || !EVP_DigestInit_ex(tmp_ctx, md, impl) ||
|
||||
!EVP_DigestUpdate(tmp_ctx, in->data, in->length) ||
|
||||
!EVP_DigestFinal_ex(tmp_ctx, (unsigned char *) out->data,
|
||||
&tmp_len))
|
||||
goto err;
|
||||
out->length = tmp_len;
|
||||
|
||||
if (!ctx)
|
||||
EVP_MD_CTX_destroy(tmp_ctx);
|
||||
|
||||
return out;
|
||||
|
||||
err:
|
||||
if (out)
|
||||
BUF_MEM_free(out);
|
||||
if (tmp_ctx && !ctx)
|
||||
EVP_MD_CTX_destroy(tmp_ctx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BUF_MEM *
|
||||
cipher(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl,
|
||||
unsigned char *key, unsigned char *iv, int enc, const BUF_MEM * in,
|
||||
int init)
|
||||
{
|
||||
BUF_MEM * out = NULL;
|
||||
EVP_CIPHER_CTX * tmp_ctx = NULL;
|
||||
int i;
|
||||
|
||||
if (!in)
|
||||
goto err;
|
||||
|
||||
if (ctx)
|
||||
tmp_ctx = ctx;
|
||||
else {
|
||||
tmp_ctx = EVP_CIPHER_CTX_new();
|
||||
if (!tmp_ctx)
|
||||
goto err;
|
||||
EVP_CIPHER_CTX_init(tmp_ctx);
|
||||
}
|
||||
|
||||
if (ctx->flags & EVP_CIPH_NO_PADDING) {
|
||||
i = in->length;
|
||||
if (in->length % EVP_CIPHER_block_size(type) != 0) {
|
||||
printf("Input length is not a multiple of block length\n");
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
i = in->length + EVP_CIPHER_block_size(type);
|
||||
|
||||
out = BUF_MEM_create(i);
|
||||
if (!out)
|
||||
goto err;
|
||||
|
||||
/* get cipher */
|
||||
if (ctx && init)
|
||||
if (!EVP_CipherInit_ex(tmp_ctx, type, impl, key, iv, enc))
|
||||
goto err;
|
||||
|
||||
if (!EVP_CipherUpdate(ctx, (unsigned char *) out->data, &i,
|
||||
(unsigned char *) in->data, in->length))
|
||||
goto err;
|
||||
out->length = i;
|
||||
|
||||
if (!EVP_CipherFinal_ex(ctx, (unsigned char *) (out->data + out->length),
|
||||
&i))
|
||||
goto err;
|
||||
|
||||
if (!(ctx->flags & EVP_CIPH_NO_PADDING))
|
||||
out->length += i;
|
||||
|
||||
if (!ctx) {
|
||||
EVP_CIPHER_CTX_cleanup(tmp_ctx);
|
||||
EVP_CIPHER_CTX_free(tmp_ctx);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
err:
|
||||
|
||||
if (out)
|
||||
BUF_MEM_free(out);
|
||||
if (!ctx && tmp_ctx) {
|
||||
EVP_CIPHER_CTX_cleanup(tmp_ctx);
|
||||
EVP_CIPHER_CTX_free(tmp_ctx);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BUF_MEM *
|
||||
add_iso_pad(const BUF_MEM * m, int block_size)
|
||||
{
|
||||
BUF_MEM * out = NULL;
|
||||
int p_len;
|
||||
|
||||
if (!m)
|
||||
goto err;
|
||||
|
||||
/* calculate length of padded message */
|
||||
p_len = (m->length / block_size) * block_size + block_size;
|
||||
|
||||
out = BUF_MEM_create(p_len);
|
||||
if (!out)
|
||||
goto err;
|
||||
|
||||
memcpy(out->data, m->data, m->length);
|
||||
|
||||
/* now add iso padding */
|
||||
memset(out->data + m->length, 0x80, 1);
|
||||
memset(out->data + m->length + 1, 0, p_len - m->length - 1);
|
||||
|
||||
return out;
|
||||
|
||||
err:
|
||||
if (out)
|
||||
BUF_MEM_free(out);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BUF_MEM *
|
||||
encoded_ssc(const uint16_t ssc, const PACE_CTX *ctx)
|
||||
{
|
||||
BUF_MEM * out = NULL;
|
||||
size_t len;
|
||||
|
||||
if (!ctx)
|
||||
goto err;
|
||||
|
||||
len = EVP_CIPHER_block_size(ctx->cipher);
|
||||
out = BUF_MEM_create(len);
|
||||
if (!out || len < sizeof ssc)
|
||||
goto err;
|
||||
|
||||
/* Copy SSC to the end of buffer and fill the rest with 0 */
|
||||
memset(out->data, 0, len);
|
||||
memcpy(out->data + len - sizeof ssc, &ssc, sizeof ssc);
|
||||
|
||||
return out;
|
||||
|
||||
err:
|
||||
if (out)
|
||||
BUF_MEM_free(out);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BUF_MEM *
|
||||
BUF_MEM_create(size_t len)
|
||||
{
|
||||
BUF_MEM *out = BUF_MEM_new();
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
if (!BUF_MEM_grow(out, len)) {
|
||||
BUF_MEM_free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BUF_MEM *
|
||||
BUF_MEM_create_init(const void *buf, size_t len)
|
||||
{
|
||||
BUF_MEM *out;
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out = BUF_MEM_create(len);
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
memcpy(out->data, buf, len);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BUF_MEM *
|
||||
point2buf(const EC_KEY * ecdh, BN_CTX * bn_ctx, const EC_POINT * ecp)
|
||||
{
|
||||
size_t len;
|
||||
BUF_MEM * out;
|
||||
|
||||
len = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), ecp,
|
||||
EC_KEY_get_conv_form(ecdh), NULL, 0, bn_ctx);
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
out = BUF_MEM_create(len);
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
out->length = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), ecp,
|
||||
EC_KEY_get_conv_form(ecdh), (unsigned char *) out->data, out->max,
|
||||
bn_ctx);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BUF_MEM *
|
||||
bn2buf(const BIGNUM *bn)
|
||||
{
|
||||
BUF_MEM * out;
|
||||
|
||||
if (!bn)
|
||||
return NULL;
|
||||
|
||||
out = BUF_MEM_create(BN_num_bytes(bn));
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
out->length = BN_bn2bin(bn, (unsigned char *) out->data);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BUF_MEM *
|
||||
BUF_MEM_dup(const BUF_MEM * in)
|
||||
{
|
||||
BUF_MEM * out = NULL;
|
||||
|
||||
if (!in)
|
||||
return NULL;
|
||||
|
||||
out = BUF_MEM_create(in->length);
|
||||
if (!out)
|
||||
goto err;
|
||||
|
||||
memcpy(out->data, in->data, in->length);
|
||||
out->max = in->max;
|
||||
|
||||
return out;
|
||||
|
||||
err:
|
||||
if (out)
|
||||
BUF_MEM_free(out);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
119
ccid/utils.h
Normal file
119
ccid/utils.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
/**
|
||||
* @date 2009-11-30
|
||||
* @version 0.1
|
||||
* @author Frank Morgner <morgner@informatik.hu-berlin.de>
|
||||
* @author Dominik Oepen <oepen@informatik.hu-berlin.de>
|
||||
*/
|
||||
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/pace.h>
|
||||
|
||||
/**
|
||||
* @brief Wrapper for the OpenSSL hash functions.
|
||||
*
|
||||
* @param md
|
||||
* @param ctx (optional)
|
||||
* @param impl (optional)
|
||||
* @param in
|
||||
*
|
||||
* @return message digest or NULL if an error occurred
|
||||
*/
|
||||
BUF_MEM *
|
||||
hash(const EVP_MD * md, EVP_MD_CTX * ctx, ENGINE * impl, const BUF_MEM * in);
|
||||
/**
|
||||
* @brief Wrapper to the OpenSSL encryption functions.
|
||||
*
|
||||
* @param ctx (optional)
|
||||
* @param type
|
||||
* @param impl only evaluated if init is 1. (optional)
|
||||
* @param key only evaluated if init is 1.
|
||||
* @param iv only evaluated if init is 1. (optional)
|
||||
* @param enc only evaluated if init is 1.
|
||||
* @param in
|
||||
* @param init whether to initialize (1) the given ctx or not (0).
|
||||
*
|
||||
* @return cipher of in or NULL if an error occurred
|
||||
*/
|
||||
BUF_MEM *
|
||||
cipher(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl,
|
||||
unsigned char *key, unsigned char *iv, int enc, const BUF_MEM * in,
|
||||
const int init);
|
||||
/**
|
||||
* @brief Padds a buffer using ISO/IEC 9797-1 padding method 2.
|
||||
*
|
||||
* @param m buffer to padd
|
||||
* @param block_size pad to this block size
|
||||
*
|
||||
* @return new buffer with the padded input or NULL if an error occurred
|
||||
*/
|
||||
BUF_MEM *
|
||||
add_iso_pad(const BUF_MEM * m, int block_size);
|
||||
/**
|
||||
* @brief Encodes a send sequence counter according to TR-3110 F.3
|
||||
*
|
||||
* @param ssc Send sequence counter to encode (Formatted in big endian)
|
||||
* @param ctx PACE_CTX object
|
||||
*
|
||||
* @return BUF_MEM object containing the send sequence counter or NULL if an error occurred
|
||||
*
|
||||
* @note This function is automatically called during PACE, normally you should not need to use it.
|
||||
*/
|
||||
BUF_MEM * encoded_ssc(const uint16_t ssc, const PACE_CTX *ctx);
|
||||
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/ec.h>
|
||||
|
||||
/**
|
||||
* @brief Creates a BUF_MEM object
|
||||
*
|
||||
* @param len required length of the buffer
|
||||
*
|
||||
* @return Initialized BUF_MEM object or NULL if an error occurred
|
||||
*/
|
||||
BUF_MEM *
|
||||
BUF_MEM_create(size_t len);
|
||||
/**
|
||||
* @brief Creates and initializes a BUF_MEM object
|
||||
*
|
||||
* @param buf Initial data
|
||||
* @param len Length of buf
|
||||
*
|
||||
* @return Initialized BUF_MEM object or NULL if an error occurred
|
||||
*/
|
||||
BUF_MEM *
|
||||
BUF_MEM_create_init(const void *buf, size_t len);
|
||||
/**
|
||||
* @brief converts an EC_POINT object to a BUF_MEM object
|
||||
*
|
||||
* @param ecdh EC_KEY object
|
||||
* @param bn_ctx object (optional)
|
||||
* @param ecp elliptic curve point to convert
|
||||
*
|
||||
* @return converted elliptic curve point or NULL if an error occurred
|
||||
*/
|
||||
BUF_MEM *
|
||||
point2buf(const EC_KEY * ecdh, BN_CTX * bn_ctx, const EC_POINT * ecp);
|
||||
/**
|
||||
* @brief converts an BIGNUM object to a BUF_MEM object
|
||||
*
|
||||
* @param bn bignumber to convert
|
||||
*
|
||||
* @return converted bignumber or NULL if an error occurred
|
||||
*/
|
||||
BUF_MEM *
|
||||
bn2buf(const BIGNUM *bn);
|
||||
/**
|
||||
* @brief duplicates a BUF_MEM structure
|
||||
*
|
||||
* @param in BUF_MEM to duplicate
|
||||
*
|
||||
* @return pointer to the new BUF_MEM or NULL in case of error
|
||||
*/
|
||||
BUF_MEM *
|
||||
BUF_MEM_dup(const BUF_MEM * in);
|
||||
#endif
|
||||
Reference in New Issue
Block a user