/* * partial PKCS15 emulation for PIV-II cards * only minimal use of the authentication cert and key * * Copyright (C) 2005, Douglas E. Engert * 2004, Nils Larsch * * Copyright (C) 2006, Identity Alliance, * Thomas Harning * * 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. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "strlcpy.h" #include "p15card-helper.h" #define MANU_ID "piv_II " int sc_pkcs15emu_piv_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *); static int piv_detect_card(sc_pkcs15_card_t *p15card) { sc_card_t *card = p15card->card; SC_FUNC_CALLED(card->ctx, 1); if (card->type < SC_CARD_TYPE_PIV_II_GENERIC || card->type >= SC_CARD_TYPE_PIV_II_GENERIC+1000) return SC_ERROR_INVALID_CARD; return SC_SUCCESS; } const objdata objects[] = { {"1", "Card Capability Container", "2.16.840.1.101.3.7.1.219.0", 0, "DB00", 0}, {"2", "Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.0", 0 , "3000", 0}, {"3", "Card Holder Fingerprints", "2.16.840.1.101.3.7.2.96.16", 0, "6010", SC_PKCS15_CO_FLAG_PRIVATE}, {"4", "Printed Information", "2.16.840.1.101.3.7.2.48.1", 0, "3001", SC_PKCS15_CO_FLAG_PRIVATE}, {"5", "Card Holder Facial Image", "2.16.840.1.101.3.7.2.96.48", 0, "6030", SC_PKCS15_CO_FLAG_PRIVATE}, {"6", "Security Object", "2.16.840.1.101.3.7.2.144.0", 0, "9000", 0}, {NULL, NULL, NULL, 0, NULL, 0} }; /* * NIST 800-73-1 is proposing to lift the restriction on * requering pin protected certs. Thus the default will be to * not require this. But there are a number of test cards * that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE * to be set. */ const cdata certs[] = { {"1", "Certificate for PIV Authentication", 0, "0101", 0}, {"2", "Certificate for Digital Signature", 0, "0100", 0}, {"3", "Certificate for Key Management", 0, "0102", 0}, #if 0 /* Strange break */ {"4", "Certificate for Card Authentication", 0, "0500", 0}, #endif {NULL, NULL, 0, NULL, 0} }; const pindata pins[] = { { "1", "PIV Card Holder pin", "", 0x80, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { "2", "PIV PUK", "", 0x81, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, /* there are some more key, but dont need for now */ /* The admin 9b might fall in here */ { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* * The size of the key or the algid is not really known * but can be derived from the certificates. * DEE need to fix - We will still refer to the "key files" as 06 even of not. * 07 is 2048, 05 is 3072. */ const pubdata pubkeys[] = { { "1", "AUTH pubkey", 1024, USAGE_AUT, "9A06", 0x9A, "1", 0}, { "2", "SIGN pubkey", 1024, USAGE_AUT, "9C06", 0x9C, "1", 0}, { "3", "KEY MAN pubkey", 1024, USAGE_AUT, "9D06", 0x9E, "1", 0}, { "4", "ADMIN pubkey", 1024, USAGE_AUT, "9B06", 0x9B, "1", 0}, { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; const prdata prkeys[] = { { "1", "AUTH key", 1024, USAGE_AUT, "", 0x9A, "1", 0}, { "2", "SIGN key", 1024, USAGE_AUT, "", 0x9C, "1", 0}, { "3", "KEY MAN key", 1024, USAGE_AUT, "", 0x9E, "1", 0}, { "4", "ADMIN key", 1024, USAGE_AUT, "", 0x9B, "1", 0}, { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; /* TEMPORARY: Should hook into card-piv ... */ static int piv_load_cached_cert(sc_card_t *card, u8** buf, size_t* count, int* should_free) { /* File already selected.. just read... */ int r; u8* out = malloc(4096*2); r = sc_read_binary(card, 0, out, 4096*2, 0); if(r < 0) { free(out); *buf = NULL; *count = 0; return r; } *count = r; *buf = out; *should_free = 1; return SC_SUCCESS; } #define CHECK_CERTIFICATES 1 static p15data_items items = { objects, certs, pins, NULL, prkeys, #ifdef CHECK_CERTIFICATES piv_load_cached_cert, #else NULL, #endif default_cert_handle, 1, #ifdef CHECK_CERTIFICATES 0, #else 1, #endif 0 }; static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) { int r; sc_card_t *card = p15card->card; SC_FUNC_CALLED(card->ctx, 1); /* could read this off card if needed */ /* CSP does not like a - in the name */ p15card->label = strdup("PIV_II"); p15card->manufacturer_id = strdup(MANU_ID); /* get serial number */ /* We could also use the CCC or CHUID info here */ #if 0 r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; p15card->serial_number = strdup(buf); #endif p15card->serial_number = strdup("9876543210"); sc_debug(card->ctx, "PIV-II adding objects..."); r = initialize_all(p15card, &items); SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); } int sc_pkcs15emu_piv_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opts) { sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; SC_FUNC_CALLED(ctx, 1); if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK) return sc_pkcs15emu_piv_init(p15card); else { int r = piv_detect_card(p15card); if (r) return SC_ERROR_WRONG_CARD; return sc_pkcs15emu_piv_init(p15card); } }