diff options
author | Rob Austein <sra@hactrn.net> | 2015-06-22 20:18:27 -0400 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2015-06-22 20:18:27 -0400 |
commit | 291a2e0b6a37ffcc3325388c5fdad63d8f185130 (patch) | |
tree | 831bceb929d07d3a826fb3012930e9c848769405 | |
parent | 67d2f799fb76197d78bbf8ab6d76557f09f30114 (diff) |
Convert from Cryptlib to libhal. Compiles, not yet tested otherwise.
-rw-r--r-- | GNUmakefile | 12 | ||||
-rw-r--r-- | pkcs11.c | 1618 | ||||
-rw-r--r-- | schema.sql | 53 |
3 files changed, 549 insertions, 1134 deletions
diff --git a/GNUmakefile b/GNUmakefile index 9277e8f..e73c757 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -28,15 +28,11 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# Change this to "../cryptlib/build" when this code moves to sw/pkcs11/. -# -#CRYPTLIB_DIR = ../cryptlib/build -CRYPTLIB_DIR = ../../../sw/cryptlib/build - +LIBHAL_DIR = ../libhal SQLITE3_DIR = ../sqlite3 -CFLAGS += -g -I${CRYPTLIB_DIR} -I${SQLITE3_DIR} -fPIC -DENABLE_CRYPTLIB_DEVICE=0 -Wall -LIBS := ${CRYPTLIB_DIR}/libcl.a ${SQLITE3_DIR}/libsqlite3.a +CFLAGS += -g3 -fPIC -Wall -std=c99 -I${LIBHAL_DIR} -I${SQLITE3_DIR} +LIBS := ${LIBHAL_DIR}/libhal.a ${SQLITE3_DIR}/libsqlite3.a all: libpkcs11.so @@ -63,5 +59,5 @@ libpkcs11.so: pkcs11.so tags: TAGS -TAGS: *.[ch] ${CRYPTLIB_DIR}/cryptlib.h ${SQLITE3_DIR}/sqlite3.h +TAGS: *.[ch] etags $^ @@ -46,7 +46,7 @@ #include <sqlite3.h> -#include "cryptlib.h" +#include <hal.h> /* * Magic PKCS #11 macros that must be defined before including @@ -100,39 +100,6 @@ #define P11_VERSION_HW_MINOR 0 /* - * A value that can't possibly be a valid Cryptlib handle. - */ - -#ifndef CRYPT_HANDLE_NONE -#define CRYPT_HANDLE_NONE (-1) -#endif - -/* - * Whether to enable hardware (FPGA) support. This option may go away - * eventually, once we have enough algorithms implemented in Verilog. - */ - -#ifndef ENABLE_CRYPTLIB_DEVICE -#define ENABLE_CRYPTLIB_DEVICE 1 -#endif - -/* - * Whehter to enable software algorithms. This is not really an - * option at the moment, as the code won't run or even build properly - * if this is disabled. It's a placeholder to let us flag bits of - * code that probably should go away if and when we're doing all the - * crypto algorithms on the FPGA. - */ - -#ifndef ENABLE_CRYPTLIB_SOFTWARE -#define ENABLE_CRYPTLIB_SOFTWARE 1 -#endif - -#if !ENABLE_CRYPTLIB_SOFTWARE -#error Code will not work correctly with software algorithm support disabled -#endif - -/* * Debugging control. */ @@ -150,19 +117,6 @@ #endif /* - * Default name for PKCS #15 keyring. Can be overriden at runtime by - * setting PKCS11_KEYRING environment variable. - * - * In the long term this probably goes away, as all keys should live - * behind the Cryptlib hardware interface, but we need something for - * initial testing. - */ - -#ifndef PKCS15_KEYRING -#define PKCS15_KEYRING ".cryptech-pkcs11.p15" -#endif - -/* * Whether to include POSIX-specific features. */ @@ -183,38 +137,25 @@ */ /* - * Cryptlib handles in the session structure are defined via a silly - * macro so that we can automate initialization and finalization - * without accidently missing any of the handles. + * At present we have no concept of encryption or signature algorithms + * in libhal, as we only support RSA and AES. For PKCS #11 purposes + * we can figure out what kind of key we're looking at from attributes + * like CKA_KEY_TYPE, so it's just something we look up given the key + * object handle. * - * Note that the encryption and decryption cases (other than raw - * encryption with no symmetric cipher algorithm) will need to use the - * enveloping API: see pp 61-62, 70-71, 190 of the Cryptlib manual. - * We may not really need to keep all the contexts around in this case - * once we've bound them into the envelope, drive off that bridge when - * we get to it. + * At the moment we don't need to keep any signature or digest state + * in the session structure, which is good since the current hash + * cores don't allow us to extract state anyway. This makes it + * impossible to implement the incremental operations + * (C_DigestUpdate(), C_SignUpdate()) but also simplifies our current + * task. * - * Syntax: One handle per line, as calls to to-be-defined macros - * SESSION_CRYPTLIB_CONTEXT() or SESSION_CRYPTLIB_ENVELOPE(), entries - * separated by semicolons, no semicolon after last entry. + * General idea is that we have separate descriptors/handles/state for + * each operation that we're allowed to do in parallel, so sign, + * verify, digest, encrypt, decrypt, wrapkey, and unwrapkey all need + * separate slots in the session structure. Add these as we go. */ -#define SESSION_CRYPTLIB_HANDLES \ - SESSION_CRYPTLIB_CONTEXT(sign_key_context); \ - SESSION_CRYPTLIB_CONTEXT(sign_digest_context); \ - SESSION_CRYPTLIB_CONTEXT(verify_key_context); \ - SESSION_CRYPTLIB_CONTEXT(verify_digest_context); \ - SESSION_CRYPTLIB_CONTEXT(digest_context) - -#if 0 - SESSION_CRYPTLIB_CONTEXT(encrypt_key_context); - SESSION_CRYPTLIB_CONTEXT(encrypt_cipher_context); - SESSION_CRYPTLIB_CONTEXT(decrypt_key_context); - SESSION_CRYPTLIB_CONTEXT(decrypt_cipher_context); - SESSION_CRYPTLIB_ENVELOPE(encrypt_envelope); - SESSION_CRYPTLIB_ENVELOPE(decrypt_envelope); -#endif - typedef struct p11_session { CK_SESSION_HANDLE handle; /* Session handle */ struct p11_session *link; /* Next session in list */ @@ -223,12 +164,10 @@ typedef struct p11_session { CK_VOID_PTR application; /* Application data */ sqlite3_stmt *find_query; /* FindObject*() query state */ int find_query_done; /* find_query has terminated */ - -#define SESSION_CRYPTLIB_CONTEXT(_ctx_) CRYPT_CONTEXT _ctx_ -#define SESSION_CRYPTLIB_ENVELOPE(_env_) CRYPT_ENVELOPE _env_ - SESSION_CRYPTLIB_HANDLES; -#undef SESSION_CRYPTLIB_ENVELOPE -#undef SESSION_CRYPTLIB_CONTEXT + const hal_hash_descriptor_t + *digest_descriptor, /* Hash for C_Digest*() */ + *sign_digest_descriptor; /* Hash for C_Sign*() */ + CK_OBJECT_HANDLE sign_key_handle; /* Key for C_Sign*() */ } p11_session_t; @@ -277,19 +216,6 @@ static p11_session_t *p11_sessions; static sqlite3 *sqldb = NULL; /* - * Saved copy of PIN (sigh). - * - * We'd like to do better than this, but as long as we're supporting - * software keysets which require a password every time we read or - * write a private key, we need this. Once we're dealing with just - * the hardware interface we should be able to skip this. - */ - -#if ENABLE_CRYPTLIB_SOFTWARE -static char *pin = NULL; -#endif - -/* * Next PKCS #11 handle to allocate. We use a single handle space for * both session and object handles, and we just keep incrementing * until it wraps, to reduce the amount of time we have to spend @@ -299,21 +225,6 @@ static char *pin = NULL; static CK_ULONG next_handle; /* - * Cryptlib handle for hardware device. - */ - -#if ENABLE_CRYPTLIB_DEVICE -static CRYPT_DEVICE cryptlib_device = CRYPT_HANDLE_NONE; -#endif - -/* - * Filenames for SQL database and PKCS #15 keyring. - */ - -static char *database_filename = NULL; -static char *keyring_filename = NULL; - -/* * Mutex callbacks. */ @@ -362,14 +273,18 @@ static pid_t initialized_pid; */ #if DEBUG_SQL + #define sql_whine(_expr_) \ (fprintf(stderr, "%s:%u: %s returned %s\n", \ __FILE__, __LINE__, #_expr_, sqlite3_errmsg(sqldb)), \ sql_breakpoint()) -#else + +#else /* DEBUG_SQL */ + #define sql_whine(_expr_) \ ((void) 0) -#endif + +#endif /* DEBUG_SQL */ #define sql_check(_good_, _expr_) \ ((_expr_) == (_good_) ? 1 : (sql_whine(_expr_), 0)) @@ -379,52 +294,31 @@ static pid_t initialized_pid; #define sql_check_done(_expr_) sql_check(SQLITE_DONE, _expr_) #define sql_whine_step() sql_whine(sqlite3_step()) - - /* - * Filename utilities. + * Error checking for libhal calls. */ -/* - * Construct name of configuration file if we don't already have it cached. - */ - -static char *cf_generate(char **fn, /* Output filename */ - const char * const env, /* Name of environment variable */ - const char * const base) /* Filename in home directory */ -{ - char *var; - - assert(fn != NULL && env != NULL && base != NULL); - - if (*fn != NULL) - return *fn; - - if ((var = getenv(env)) != NULL && (*fn = malloc(strlen(var) + 1)) != NULL) - strcpy(*fn, var); +#ifndef DEBUG_HAL +#define DEBUG_HAL 0 +#endif - else if (var == NULL && (var = getenv("HOME")) != NULL && (*fn = malloc(strlen(var) + strlen(base) + 2)) != NULL) - sprintf(*fn, "%s/%s", var, base); - - else if (var == NULL && (*fn = malloc(strlen(base) + 1)) != NULL) - strcpy(*fn, base); +#if DEBUG_HAL - return *fn; +static int _hal_check(const hal_error_t err, const char * const expr, const const * const file, const unsigned line) +{ + if (err == HAL_OK) + return 1; + fprintf(stderr, "%s:%u: %s returned %s\n", file, line, hal_errorstring(err), expr); + return 0; } -/* - * Closures over cf_generate() for particular filenames. - */ +#define hal_check(_expr_) (_hal_check((_expr_), #_expr_, __FILE__, __LINE__)) -static char *cf_sql_database(void) -{ - return cf_generate(&database_filename, "PKCS11_DATABASE", SQL_DATABASE); -} +#else /* DEBUG_HAL */ -static char *cf_pkcs15_keyring(void) -{ - return cf_generate(&keyring_filename, "PKCS11_KEYRING", PKCS15_KEYRING); -} +#define hal_check(_expr_) ((_expr_) == HAL_OK) + +#endif /* DEBUG_HAL */ @@ -595,130 +489,6 @@ static CK_RV posix_mutex_unlock(CK_VOID_PTR pMutex) /* - * Wrappers around some of Cryptlib's context functions, so that the - * rest of the code can mostly ignore whether a particular algorithm - * is implemented in hardware or not. In theory, we could achieve - * this simply by always trying cryptDeviceCreateContext() and - * checking its return code to see whether we should fall back to - * CryptCreateContext(), but for the moment I'm more comfortable with - * explictly coding the list of algorithms we expect to be supported - * here. This may change at some future date, once the HAL code is a - * little further along. - */ - -static int cryptlib_implemented_in_hardware(const CRYPT_ALGO_TYPE algo) -{ -#if ENABLE_CRYPTLIB_DEVICE - switch (algo) { - case CRYPT_ALGO_YOU_NEED_TO_SPECIFY_SOMETHING_HERE_BOZO: - return 1; - } -#endif - - return 0; -} - -/* - * Create a context -- hardware if supported, software otherwise. - */ - -static C_RET cryptlib_create_context(CRYPT_CONTEXT *ctx, const CRYPT_ALGO_TYPE algo) -{ -#if ENABLE_CRYPTLIB_DEVICE - if (cryptlib_implemented_in_hardware(algo)) - return cryptDeviceCreateContext(cryptlib_device, ctx, algo); -#endif - - return cryptCreateContext(ctx, CRYPT_UNUSED, algo); -} - -/* - * Store a key. This is a no-op for hardware contexts (the hardware - * device functions as a key store), but requires writing to the PKCS - * #15 keyring for software contexts. - */ - -static C_RET cryptlib_store_key(const CRYPT_CONTEXT ctx) -{ - CRYPT_KEYSET keyset; - int ret, algo; - - if ((ret = cryptGetAttribute(ctx, CRYPT_CTXINFO_ALGO, &algo)) != CRYPT_OK) - return ret; - - if (cryptlib_implemented_in_hardware(algo)) - return CRYPT_OK; - - ret = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, cf_pkcs15_keyring(), CRYPT_KEYOPT_NONE); - - if (ret == CRYPT_ERROR_OPEN || ret == CRYPT_ERROR_NOTFOUND) - ret = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, cf_pkcs15_keyring(), CRYPT_KEYOPT_CREATE); - - if (ret != CRYPT_OK) - return ret; - - ret = cryptAddPrivateKey(keyset, ctx, pin); - - cryptKeysetClose(keyset); - - return ret; -} - -/* - * Load a key. This creates a new context. - */ - -static C_RET cryptlib_load_key(CRYPT_CONTEXT *ctx, const char *keyid) -{ - CRYPT_KEYSET keyset; - int ret; - - assert(ctx != NULL); - - *ctx = CRYPT_HANDLE_NONE; - -#if ENABLE_CRYPTLIB_DEVICE - if ((ret = cryptGetPrivateKey(cryptlib_device, ctx, CRYPT_KEYID_NAME, keyid, NULL)) == CRYPT_OK) - return ret; -#endif - - if ((ret = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, cf_pkcs15_keyring(), CRYPT_KEYOPT_READONLY)) != CRYPT_OK) - return ret; - - ret = cryptGetPrivateKey(keyset, ctx, CRYPT_KEYID_NAME, keyid, pin); - - cryptKeysetClose(keyset); - - return ret; -} - -/* - * Delete a key. - */ - -static C_RET cryptlib_delete_key(const char *keyid) -{ - CRYPT_KEYSET keyset; - int ret; - -#if ENABLE_CRYPTLIB_DEVICE - if ((ret = cryptDeleteKey(cryptlib_device, CRYPT_KEYID_NAME, keyid)) == CRYPT_OK) - return ret; -#endif - - if ((ret = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, cf_pkcs15_keyring(), CRYPT_KEYOPT_NONE)) != CRYPT_OK) - return ret; - - ret = cryptDeleteKey(keyset, CRYPT_KEYID_NAME, keyid); - - cryptKeysetClose(keyset); - - return ret; -} - - - -/* * SQL utilities. */ @@ -766,7 +536,26 @@ static int sql_init(void) assert(sqldb == NULL); - return sql_check_ok(sqlite3_open(cf_sql_database(), &sqldb)) && sql_exec(schema); + const char * const env = getenv("PKCS11_DATABASE"); + const char * const home = getenv("HOME"); + const char * const base = SQL_DATABASE; + int ok; + + if (env != NULL) { + ok = sql_check_ok(sqlite3_open(env, &sqldb)); + } + + else if (home == NULL) { + ok = sql_check_ok(sqlite3_open(base, &sqldb)); + } + + else { + char fn[strlen(home) + strlen(base) + 2]; + snprintf(fn, sizeof(fn), "%s/%s", home, base); + ok = sql_check_ok(sqlite3_open(fn, &sqldb)); + } + + return ok && sql_exec(schema); } /* @@ -825,150 +614,68 @@ static int sql_prepare(sqlite3_stmt **q, const char *format, ...) return sqlite3_prepare_v2(sqldb, buffer, -1, q, NULL); } - - /* - * (Extremely) minimal ASN.1 parser, just good enough to pick a few - * fields out of something like a well-formed ASN.1 DER representation - * of a certificate. + * This idiom occurs frequently, bundle it so we have the option of + * doing it along with the normal conditional control flow that SQL + * queries seem to follow. */ -#define ASN1_UNIVERSAL 0x00 -#define ASN1_APPLICATION 0x40 -#define ASN1_CONTEXT_SPECIFIC 0x80 -#define ASN1_PRIVATE 0xC0 +static int sql_finalize_and_clear(sqlite3_stmt **q) +{ + assert(q != NULL); -#define ASN1_PRIMITIVE 0x00 -#define ASN1_CONSTRUCTED 0x20 + int err = sqlite3_finalize(*q); -#define ASN1_TAG_MASK 0x1F + if (err != SQLITE_OK) + return err; -#define ASN1_INTEGER (ASN1_PRIMITIVE | 0x02) -#define ASN1_BIT_STRING (ASN1_PRIMITIVE | 0x03) -#define ASN1_OCTET_STRING (ASN1_PRIMITIVE | 0x04) -#define ASN1_NULL (ASN1_PRIMITIVE | 0x05) -#define ASN1_OBJECT_IDENTIFIER (ASN1_PRIMITIVE | 0x06) -#define ASN1_SEQUENCE (ASN1_CONSTRUCTED | 0x10) -#define ASN1_SET (ASN1_CONSTRUCTED | 0x11) + *q = NULL; + return SQLITE_OK; +} -#define ASN1_EXPLICIT_CONTEXT (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED) -#define ASN1_EXPLICIT_0 (ASN1_EXPLICIT_CONTEXT + 0) + /* - * Common setup code for asn1_dive() and asn1_skip(). + * Initialize KEK. If we had proper hardware support the KEK would be + * living in special RAM where we could wipe it if anything triggered + * our tamper circuitry. But we have no such at the moment, so we + * have no good place to store the KEK. * - * Check ASN.1 tag and various errors, decode length field. - * Outputs are length of header (tag + length) and value. + * So we store it in the SQL database, which kind of defeats the point + * of wrapping private keys that live in the same database -- except + * that we're trying to get all the other bits right so that we can + * just move the KEK to secure memory once we have it. */ -static int asn1_prep(const unsigned char tag, - const unsigned char * const der, - const size_t len, - size_t *phlen, - size_t *pvlen) +static int kek_init(void) { - size_t i, hlen, vlen; - - if (der == NULL || len < 2 || phlen == NULL || pvlen == NULL || der[0] != tag || der[1] > 0x84) - return 0; - - if ((der[1] & 0x80) == 0) { - hlen = 2; - vlen = der[1]; - } + static const char test_kek[] = + " SELECT kek IS NULL FROM global"; - else { - hlen = 2 + (der[1] & 0x7F); - vlen = 0; + static const char set_kek[] = + " UPDATE global SET kek = ?1"; - if (hlen >= len) - return 0; + sqlite3_stmt *q = NULL; - for (i = 2; i < hlen; i++) - vlen = (vlen << 8) + der[i]; - } + int ok = (sql_check_ok(sql_prepare(&q, test_kek)) && + sql_check_row(sqlite3_step(q))); - if (hlen + vlen > len) - return 0; + if (ok && sqlite3_column_int(q, 0)) { + uint8_t kekbuf[bitsToBytes(256)]; - *phlen = hlen; - *pvlen = vlen; - return 1; -} + ok = (hal_check(hal_get_random(kekbuf, sizeof(kekbuf))) && + sql_check_ok(sql_finalize_and_clear(&q)) && + sql_check_ok(sql_prepare(&q, set_kek)) && + sql_check_ok(sqlite3_bind_blob(q, 1, kekbuf, + sizeof(kekbuf), + NULL)) && + sql_check_done(sqlite3_step(q))); -/* - * Dive into an ASN.1 object. - * - * The special handling for BIT STRING is only appropriate for the - * intended use, where BIT STRING always encapsulates another ASN.1 - * object like SubjectPublicKeyInfo and is thus always required to be - * a multiple of 8 bits in length. If we ever need to use this code - * to deal with real bit strings, the special handling will need to - * move to a separate function which we can call when appropriate. - */ - -static int asn1_dive(const unsigned char tag, - const unsigned char **der, - size_t *len) -{ - size_t hlen, vlen; - - if (der == NULL || len == NULL || !asn1_prep(tag, *der, *len, &hlen, &vlen)) - return 0; - - if (tag == ASN1_BIT_STRING) { - if (vlen == 0 || hlen >= *len || (*der)[hlen] != 0x00) - return 0; - hlen++, vlen--; + memset(kekbuf, 0, sizeof(kekbuf)); } - assert(hlen + vlen <= *len); - *der += hlen; /* Advance past the header */ - *len = vlen; /* Shrink range to be just the content */ - return 1; -} - -/* - * Skip over an ASN.1 object. - */ - -static int asn1_skip(const unsigned char tag, - const unsigned char **der, - size_t *len) -{ - size_t hlen, vlen; - - if (der == NULL || len == NULL || !asn1_prep(tag, *der, *len, &hlen, &vlen)) - return 0; - - assert(hlen + vlen <= *len); - *der += hlen + vlen; /* Advance past entire object */ - *len -= hlen + vlen; /* Reduce range by length of object */ - return 1; -} - -/* - * Grovel through a DER encoded X.509v3 certificate object until we - * find the subjectPublicKey field. See the ASN.1 in RFC 5280. - * - * This is much too simplistic for general use, but should suffice to - * pick the subjectPublicKey data out of a certificate generated for - * us by Cryptlib. - */ - -static int asn1_find_x509_spki(const unsigned char **der, size_t *len) -{ - return (asn1_dive(ASN1_SEQUENCE, der, len) && /* Dive into certificate */ - asn1_dive(ASN1_SEQUENCE, der, len) && /* Dive into tbsCertificate */ - asn1_skip(ASN1_EXPLICIT_0, der, len) && /* Skip version */ - asn1_skip(ASN1_INTEGER, der, len) && /* Skip serialNumber */ - asn1_skip(ASN1_SEQUENCE, der, len) && /* Skip signature */ - asn1_skip(ASN1_SEQUENCE, der, len) && /* Skip issuer */ - asn1_skip(ASN1_SEQUENCE, der, len) && /* skip validity */ - asn1_skip(ASN1_SEQUENCE, der, len) && /* Skip subject */ - asn1_dive(ASN1_SEQUENCE, der, len) && /* Dive into subjectPublicKeyInfo */ - asn1_skip(ASN1_SEQUENCE, der, len) && /* Skip algorithm */ - asn1_dive(ASN1_BIT_STRING, der, len)); /* Dive into subjectPublicKey */ + sqlite3_finalize(q); + return ok; } @@ -1201,8 +908,15 @@ static int p11_attribute_find_in_template(const CK_ATTRIBUTE_TYPE type, * values, it may be necessary to defer calling this method until * after the default and mandatory values have been merged into the * values supplied by the application-supplied template. + * + * Semantics of the flags follow RFC 5280 4.2.1.3, numeric values + * don't matter particularly as we only use them internally. */ +#define KEYUSAGE_DIGITALSIGNATURE (1 << 0) +#define KEYUSAGE_KEYENCIPHERMENT (1 << 1) +#define KEYUSAGE_DATAENCIPHERMENT (1 << 2) + static void p11_attribute_apply_keyusage(unsigned *keyusage, const CK_ATTRIBUTE_TYPE type, const CK_BBOOL *value) { unsigned flag; @@ -1212,15 +926,15 @@ static void p11_attribute_apply_keyusage(unsigned *keyusage, const CK_ATTRIBUTE_ switch (type) { case CKA_SIGN: /* Generate signature */ case CKA_VERIFY: /* Verify signature */ - flag = CRYPT_KEYUSAGE_DIGITALSIGNATURE; + flag = KEYUSAGE_DIGITALSIGNATURE; break; case CKA_ENCRYPT: /* Encrypt bulk data (seldom used) */ case CKA_DECRYPT: /* Bulk decryption (seldom used) */ - flag = CRYPT_KEYUSAGE_DATAENCIPHERMENT; + flag = KEYUSAGE_DATAENCIPHERMENT; break; case CKA_WRAP: /* Wrap key (normal way of doing encryption) */ case CKA_UNWRAP: /* Unwrap key (normal way of doing decryption) */ - flag = CRYPT_KEYUSAGE_KEYENCIPHERMENT; + flag = KEYUSAGE_KEYENCIPHERMENT; break; default: return; /* Attribute not related to key usage */ @@ -1370,11 +1084,6 @@ static CK_RV p11_object_check_rights(const p11_session_t *session, static int p11_object_delete_all_private(void) { - static const char select_format[] = - " WITH" - " private AS (SELECT session_object_id FROM session_attribute WHERE type = %u AND value <> X'00')" - " SELECT keyid FROM session_object WHERE keyid IS NOT NULL AND session_object_id IN private"; - static const char delete_format[] = " WITH" " s AS (SELECT session_object_id FROM session_attribute WHERE type = %u AND value <> X'00')," @@ -1382,22 +1091,7 @@ static int p11_object_delete_all_private(void) " DELETE FROM object WHERE token_object_id IN t OR session_object_id IN s"; sqlite3_stmt *q = NULL; - int ret, ok = 0; - - if (!sql_check_ok(sql_prepare(&q, select_format, CKA_PRIVATE))) - goto fail; - - while ((ret = sqlite3_step(q)) == SQLITE_ROW) - if (cryptlib_delete_key((const char *) sqlite3_column_text(q, 0)) != CRYPT_OK) - goto fail; - - if (ret != SQLITE_DONE) { - sql_whine_step(); - goto fail; - } - - sqlite3_finalize(q); - q = NULL; + int ok = 0; if (!sql_check_ok(sql_prepare(&q, delete_format, CKA_PRIVATE, CKA_PRIVATE)) || !sql_check_done(sqlite3_step(q))) @@ -1467,8 +1161,8 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session, object_id = sqlite3_last_insert_rowid(sqldb); - sqlite3_finalize(q); - q = NULL; + if (!sql_check_ok(sql_finalize_and_clear(&q))) + goto fail; switch (flavor) { @@ -1477,16 +1171,13 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session, !sql_check_done(sqlite3_step(q))) goto fail; token_object_id = sqlite3_last_insert_rowid(sqldb); - sqlite3_finalize(q); - q = NULL; - if (!sql_check_ok(sql_prepare(&q, update_object_token_object)) || + if (!sql_check_ok(sql_finalize_and_clear(&q)) || + !sql_check_ok(sql_prepare(&q, update_object_token_object)) || !sql_check_ok(sqlite3_bind_int64(q, 1, token_object_id)) || !sql_check_ok(sqlite3_bind_int64(q, 2, object_id)) || - !sql_check_done(sqlite3_step(q))) - goto fail; - sqlite3_finalize(q); - q = NULL; - if (!sql_check_ok(sql_prepare(&q, insert_token_attribute)) || + !sql_check_done(sqlite3_step(q)) || + !sql_check_ok(sql_finalize_and_clear(&q)) || + !sql_check_ok(sql_prepare(&q, insert_token_attribute)) || !sql_check_ok(sqlite3_bind_int64(q, 1, token_object_id))) goto fail; break; @@ -1497,17 +1188,14 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session, !sql_check_done(sqlite3_step(q))) goto fail; session_object_id = sqlite3_last_insert_rowid(sqldb); - sqlite3_finalize(q); - q = NULL; - if (!sql_check_ok(sql_prepare(&q, update_object_session_object)) || + if (!sql_check_ok(sql_finalize_and_clear(&q)) || + !sql_check_ok(sql_prepare(&q, update_object_session_object)) || !sql_check_ok(sqlite3_bind_int64(q, 1, session->handle)) || !sql_check_ok(sqlite3_bind_int64(q, 2, session_object_id)) || !sql_check_ok(sqlite3_bind_int64(q, 3, object_id)) || - !sql_check_done(sqlite3_step(q))) - goto fail; - sqlite3_finalize(q); - q = NULL; - if (!sql_check_ok(sql_prepare(&q, insert_session_attribute)) || + !sql_check_done(sqlite3_step(q)) || + !sql_check_ok(sql_finalize_and_clear(&q)) || + !sql_check_ok(sql_prepare(&q, insert_session_attribute)) || !sql_check_ok(sqlite3_bind_int64(q, 1, session_object_id))) goto fail; break; @@ -1584,188 +1272,111 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session, } /* - * Get the keyid for an object. + * Store an RSA private key. * - * This may require calculating the keyid from the CKA_ID attribute. + * Write the key as PKCS #1.5 RSAPrivateKey DER, encrypt that using + * AES key wrap, and store the result as an SQL blob. + * + * We jump through a few minor hoops to let us do all the encoding and + * wrapping in place in a single buffer. */ -static int p11_object_get_keyid(const CK_OBJECT_HANDLE object_handle, - char *keyid, - const size_t maxkeyid) +static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle, + const hal_rsa_key_t key) { - static const char select_format[] = - " SELECT keyid FROM %s_object NATURAL JOIN object WHERE object_handle = ?"; + static const char select_kek[] = + " SELECT kek FROM global"; static const char update_format[] = - " UPDATE %s_object SET keyid = ?1" - " WHERE %s_object_id = (SELECT %s_object_id FROM object WHERE object_handle =?2)"; + " UPDATE %s_object SET private_key = ?1" + " WHERE %s_object_id = (SELECT %s_object_id FROM object WHERE object_handle = ?2)"; + uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(hal_rsa_key_to_der_len(key))]; const char *flavor = is_token_handle(object_handle) ? "token" : "session"; - sqlite3_stmt *q = NULL; + size_t len; int ok = 0; - if (!sql_check_ok(sql_prepare(&q, select_format, flavor)) || - !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) || - !sql_check_row(sqlite3_step(q))) + if (!sql_check_ok(sql_prepare(&q, select_kek)) || + !sql_check_row(sqlite3_step(q)) || + sqlite3_column_type(q, 0) == SQLITE_NULL || + !hal_check(hal_rsa_key_to_der(key, wrapbuf+8, &len, sizeof(wrapbuf)-8)) || + !hal_check(hal_aes_keywrap(sqlite3_column_blob(q, 0), + sqlite3_column_bytes(q, 0), + wrapbuf+8, len, wrapbuf, &len)) || + !sql_check_ok(sql_finalize_and_clear(&q)) || + !sql_check_ok(sql_prepare(&q, update_format, flavor, flavor, flavor)) || + !sql_check_ok(sqlite3_bind_blob( q, 1, wrapbuf, len, NULL)) || + !sql_check_ok(sqlite3_bind_int64(q, 2, object_handle)) || + !sql_check_done(sqlite3_step(q))) goto fail; - if (sqlite3_column_type(q, 0) == SQLITE_NULL) { - - /* - * No keyid set yet, have to create one. We use the CKA_ID - * attribute for this, zero-filling or truncating as necessary. - */ - - const CK_ULONG target_length = (CRYPT_MAX_TEXTSIZE < maxkeyid ? CRYPT_MAX_TEXTSIZE : (maxkeyid - 1)) / 2; - unsigned char id[CRYPT_MAX_HASHSIZE]; - CK_ULONG len; - int i; - - assert(target_length > 0 && target_length <= sizeof(id) && target_length * 2 < maxkeyid); - - if (!p11_attribute_get(object_handle, CKA_ID, id, &len, sizeof(id))) - goto fail; - - if (len < target_length) { - memmove(id + target_length - len, id, len); - memset(id, 0x00, target_length - len); - } - - for (i = 0; i < target_length; i++) - sprintf(keyid + (2 * i), "%02x", id[i]); - keyid[target_length * 2] = '\0'; - - sqlite3_finalize(q); - q = NULL; - - if (!sql_check_ok(sql_prepare(&q, update_format, flavor, flavor, flavor)) || - !sql_check_ok(sqlite3_bind_text( q, 1, keyid, strlen(keyid), NULL)) || - !sql_check_ok(sqlite3_bind_int64(q, 2, object_handle)) || - !sql_check_done(sqlite3_step(q))) - goto fail; - - } else { - - /* - * Already had a keyid, just have to copy it. - */ - - int len = sqlite3_column_bytes(q, 0); - - if (len >= maxkeyid) - goto fail; - - memcpy(keyid, sqlite3_column_text(q, 0), len); - keyid[len] = '\0'; - - } - ok = 1; fail: + memset(wrapbuf, 0, sizeof(wrapbuf)); sqlite3_finalize(q); return ok; } /* - * Add attributes representing the SPKI value of a key we've - * generated. + * Fetch an RSA private key. * - * Cryptlib does such a complete job of protecting our keys that it's - * rather tedious to extract the raw subjectPublicKeyInfo, but the - * PKCS #11 client needs that information, so we have to jump through - * some silly hoops. This routine does most of the work, but uses a - * separate handler (supplied as an argument) to generate attributes - * based on mechanism-specific data from the subjectPublicKey. + * Retrieve SQL blob from the object, unwrap that to get the DER + * encoding of a PKCS #1.5 RSAPrivateKey object, load the key from + * that. * - * Basic approach here is to generate a temporary certificate from the - * key, export that as DER, parse the DER for the data we need, and - * destroy the temporary certificate. + * If the key isn't set, we return success with null key. */ -static int p11_object_add_spki(const CK_OBJECT_HANDLE public_handle, - const CK_OBJECT_HANDLE private_handle, - const CRYPT_CONTEXT key, - int (*handler)(const CK_OBJECT_HANDLE, - const CK_OBJECT_HANDLE, - const unsigned char *, - const size_t)) +static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle, + hal_rsa_key_t *key, + uint8_t *keybuf, const size_t keybuf_len) { - static const char label[] = "Don't care"; - CRYPT_CERTIFICATE cert = CRYPT_HANDLE_NONE; - unsigned char *buffer = NULL; - const unsigned char *der; - int ilen, ok = 0; - size_t ulen; - - if (handler == NULL || - cryptCreateCert(&cert, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTIFICATE) != CRYPT_OK || - cryptSetAttribute(cert, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, key) != CRYPT_OK || - cryptSetAttribute(cert, CRYPT_CERTINFO_XYZZY, 1) != CRYPT_OK || - cryptSetAttributeString(cert, CRYPT_CERTINFO_COMMONNAME, label, sizeof(label)) != CRYPT_OK || - cryptSignCert(cert, key) != CRYPT_OK || - cryptExportCert(NULL, 0, &ilen, CRYPT_CERTFORMAT_CERTIFICATE, cert) != CRYPT_OK || - (der = buffer = malloc(ulen = (size_t) ilen)) == NULL || - cryptExportCert(buffer, ilen, &ilen, CRYPT_CERTFORMAT_CERTIFICATE, cert) != CRYPT_OK || - !asn1_find_x509_spki(&der, &ulen) || - !handler(public_handle, private_handle, der, ulen)) - goto fail; - - ok = 1; - - fail: - if (buffer != NULL) - free(buffer); - if (cert != CRYPT_HANDLE_NONE) - cryptDestroyCert(cert); - return ok; -} + static const char select_format[] = + " SELECT kek, private_key FROM global, %s_object NATURAL JOIN object WHERE object_handle = ?1"; -/* - * RSA-specific handler to go with p11_object_add_spki(). - * - * Extract RSA modulus and public exponent from the subjectPublicKey - * and adds the appropriate attributes to the public and private keys. - */ + const char *flavor = is_token_handle(object_handle) ? "token" : "session"; + sqlite3_stmt *q = NULL; + int ok; -static int p11_object_add_spki_rsa(const CK_OBJECT_HANDLE public_handle, - const CK_OBJECT_HANDLE private_handle, - const unsigned char *der, - const size_t len) -{ - const unsigned char *modulus = der, *publicExponent = der; - size_t modulus_len = len, publicExponent_len = len; + assert(key != NULL && keybuf != NULL); /* - * Dig the relevant integers out of the ASN.1. + * Pull everything we need from the database. */ - if (!asn1_dive(ASN1_SEQUENCE, &modulus, &modulus_len) || - !asn1_dive(ASN1_INTEGER, &modulus, &modulus_len) || - !asn1_dive(ASN1_SEQUENCE, &publicExponent, &publicExponent_len) || - !asn1_skip(ASN1_INTEGER, &publicExponent, &publicExponent_len) || - !asn1_dive(ASN1_INTEGER, &publicExponent, &publicExponent_len)) - return 0; - /* - * ASN.1 INTEGERs are signed while PKCS #11 "big integers" are - * unsigned, so skip leading zero byte, if present. - */ + if (!sql_check_ok(sql_prepare(&q, select_format, flavor)) || + !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) || + !sql_check_row(sqlite3_step(q)) || + sqlite3_column_type(q, 0) == SQLITE_NULL) { + ok = 0; + } - if (modulus_len > 0 && *modulus == 0x00) - modulus_len--, modulus++; + else if (sqlite3_column_type(q, 1) == SQLITE_NULL) { + key->key = NULL; + ok = 1; + } - if (publicExponent_len > 0 && *publicExponent == 0x00) - publicExponent_len--, publicExponent++; - - /* - * Insert the attributes and we're done. - */ + else { + const uint8_t * const kek = sqlite3_column_blob(q, 0); + const uint8_t * const pkey = sqlite3_column_blob(q, 1); + const size_t kek_len = sqlite3_column_bytes(q, 0); + const size_t pkey_len = sqlite3_column_bytes(q, 1); + uint8_t wrapbuf[sqlite3_column_bytes(q, 1)]; + size_t wrapbuf_len; - return (p11_attribute_set(public_handle, CKA_MODULUS, modulus, modulus_len) && - p11_attribute_set(public_handle, CKA_PUBLIC_EXPONENT, publicExponent, publicExponent_len) && - p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len) && - p11_attribute_set(private_handle, CKA_PUBLIC_EXPONENT, publicExponent, publicExponent_len)); + ok = (hal_check(hal_aes_keyunwrap(kek, kek_len, pkey, pkey_len, wrapbuf, &wrapbuf_len)) && + hal_check(hal_rsa_key_from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len))); + + memset(wrapbuf, 0, sizeof(wrapbuf)); + } + + if (!ok || key->key == NULL) + memset(keybuf, 0, keybuf_len); + + sqlite3_finalize(q); + return ok; } @@ -1784,13 +1395,6 @@ static p11_session_t *p11_session_new(void) if (session == NULL) return NULL; memset(session, 0, sizeof(*session)); - -#define SESSION_CRYPTLIB_CONTEXT(_ctx_) session->_ctx_ = CRYPT_HANDLE_NONE -#define SESSION_CRYPTLIB_ENVELOPE(_env_) session->_env_ = CRYPT_HANDLE_NONE - SESSION_CRYPTLIB_HANDLES; -#undef SESSION_CRYPTLIB_ENVELOPE -#undef SESSION_CRYPTLIB_CONTEXT - return session; } @@ -1803,14 +1407,7 @@ static void p11_session_free(p11_session_t *session) if (session == NULL) return; - if (session->find_query != NULL) - sqlite3_finalize(session->find_query); - -#define SESSION_CRYPTLIB_CONTEXT(_ctx_) if (session->_ctx_ != CRYPT_HANDLE_NONE) cryptDestroyContext(session->_ctx_) -#define SESSION_CRYPTLIB_ENVELOPE(_env_) if (session->_env_ != CRYPT_HANDLE_NONE) cryptDestroyEnvelope(session->_env_) - SESSION_CRYPTLIB_HANDLES; -#undef SESSION_CRYPTLIB_ENVELOPE -#undef SESSION_CRYPTLIB_CONTEXT + sql_finalize_and_clear(&session->find_query); free(session); } @@ -1876,45 +1473,21 @@ static p11_session_t *p11_session_find(const CK_SESSION_HANDLE session_handle) * Delete a session: remove it from SQL and free the session data * structure. * - * Since this destroys all associated session objects, we also have to - * delete any keys we might be holding for session objects. - * * This method assumes the move-to-the-front behavior of * p11_session_find(). */ static CK_RV p11_session_delete(const CK_SESSION_HANDLE session_handle) { - static const char select_keyid[] = - " SELECT keyid FROM session NATURAL JOIN session_object" - " WHERE session_handle = ?1 AND keyid IS NOT NULL"; - static const char delete_session[] = " DELETE FROM session WHERE session_handle = ?"; p11_session_t *session = p11_session_find(session_handle); sqlite3_stmt *q = NULL; CK_RV rv = CKR_OK; - int ret; if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - - if (!sql_check_ok(sql_prepare(&q, select_keyid)) || - !sql_check_ok(sqlite3_bind_int64(q, 1, session_handle))) - lose(CKR_FUNCTION_FAILED); - - while ((ret = sqlite3_step(q)) == SQLITE_ROW) - if (cryptlib_delete_key((const char *) sqlite3_column_text(q, 0)) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - if (ret != SQLITE_DONE) { - sql_whine_step(); - lose(CKR_FUNCTION_FAILED); - } - - sqlite3_finalize(q); - q = NULL; if (!sql_check_ok(sql_prepare(&q, delete_session)) || !sql_check_ok(sqlite3_bind_int64(q, 1, session_handle)) || @@ -1934,41 +1507,18 @@ static CK_RV p11_session_delete(const CK_SESSION_HANDLE session_handle) /* * Delete all sessions. - * - * Like p11_session_delete(), this must also delete any keys held in - * session objects. */ -static CK_RV p11_session_delete_all(void) -{ - static const char select_keys[] = - " SELECT keyid FROM session_object WHERE keyid IS NOT NULL"; - #warning Should this also clear the object table? +static CK_RV p11_session_delete_all(void) +{ static const char delete_all_sessions[] = " DELETE FROM session"; p11_session_t *session; - sqlite3_stmt *q = NULL; - int ret = SQLITE_OK; CK_RV rv = CKR_OK; - if (!sql_check_ok(sql_prepare(&q, select_keys))) - lose(CKR_FUNCTION_FAILED); - - while ((ret = sqlite3_step(q)) == SQLITE_ROW) - if (cryptlib_delete_key((const char *) sqlite3_column_text(q, 0)) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - if (ret != SQLITE_DONE) { - sql_whine_step(); - lose(CKR_FUNCTION_FAILED); - } - - sqlite3_finalize(q); - q = NULL; - if (!sql_exec(delete_all_sessions)) lose(CKR_FUNCTION_FAILED); @@ -1979,7 +1529,6 @@ static CK_RV p11_session_delete_all(void) } fail: - sqlite3_finalize(q); return rv; } @@ -2156,15 +1705,10 @@ static CK_RV p11_check_keypair_attributes_check_template_2(const p11_session_t * * amount of checking. We automate as much of the dumb stuff as * possible through the object descriptor. * - * Key usage handling here is based on RFC 5280 4.2.1.3, same as - * Cryptlib. We reuse Cryptlib's bit flags because they're - * convenient. + * Key usage handling here is based on RFC 5280 4.2.1.3. * - * We use the PKCS #11 CKA_ID attribute to generate the Cryptlib key - * label. PKCS #11 suggests but does not require CKA_ID values for - * public and private key to match; we do insist on this, because we - * really only have one key label which applies to both the public and - * private keys. + * PKCS #11 suggests but does not require CKA_ID values for public and + * private key to match. */ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, @@ -2176,8 +1720,6 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, const p11_descriptor_t * const private_descriptor) { unsigned public_keyusage = 0, private_keyusage = 0; - const CK_BYTE *id = NULL; - size_t id_len = 0; CK_RV rv = CKR_OK; int i; @@ -2208,11 +1750,6 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, goto fail; p11_attribute_apply_keyusage(&public_keyusage, type, val); - - if (type == CKA_ID) { - id = val; - id_len = len; - } } for (i = 0; i < ulPrivateKeyAttributeCount; i++) { @@ -2224,14 +1761,6 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, goto fail; p11_attribute_apply_keyusage(&private_keyusage, type, val); - - if (type == CKA_ID && id == NULL) { - id = val; - id_len = len; - } - - if (type == CKA_ID && (len != id_len || memcmp(id, val, len))) - lose(CKR_TEMPLATE_INCONSISTENT); } /* @@ -2243,13 +1772,6 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, lose(CKR_TEMPLATE_INCONSISTENT); /* - * We require a key ID. - */ - - if (id == NULL || id_len == 0) - lose(CKR_TEMPLATE_INCOMPLETE); - - /* * Check that all required attributes have been specified. */ @@ -2294,11 +1816,15 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE; handle_flavor_t public_handle_flavor = handle_flavor_session_object; handle_flavor_t private_handle_flavor = handle_flavor_session_object; - char keyid[CRYPT_MAX_HASHSIZE * 2 + 1]; - CRYPT_CONTEXT ctx = CRYPT_HANDLE_NONE; - const CK_BYTE *id = NULL; + uint8_t + keybuf[hal_rsa_key_t_size], + modulus[hal_rsa_key_t_size/8], + public_exponent[hal_rsa_key_t_size/8]; + size_t + modulus_len, + public_exponent_len; + hal_rsa_key_t key = { NULL }; CK_ULONG keysize = 0; - size_t id_len = 0; CK_RV rv; int i; @@ -2316,8 +1842,6 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, pPublicKeyTemplate != NULL && phPublicKey != NULL && pPrivateKeyTemplate != NULL && phPrivateKey != NULL); - memset(keyid, 0, sizeof(keyid)); - /* * Grab values and perform mechanism-specific checks. */ @@ -2335,12 +1859,7 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, public_handle_flavor = p11_handle_flavor_from_cka_token(val); continue; - case CKA_ID: /* We use PKCS #11 "ID" as Cryptlib label */ - id = val; - id_len = len; - continue; - - case CKA_MODULUS_BITS: /* Keysize in bits -- Cryptlib only allows multiples of 8 */ + case CKA_MODULUS_BITS: /* Keysize in bits -- only allow multiples of 8 */ keysize = *(CK_ULONG *) val; if ((keysize & 7) != 0) return CKR_ATTRIBUTE_VALUE_INVALID; @@ -2362,52 +1881,40 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, private_handle_flavor = p11_handle_flavor_from_cka_token(val); continue; - case CKA_ID: /* We use PKCS #11 "ID" as Cryptlib label */ - id = val; - id_len = len; - continue; - } } /* - * We require a key ID and a key size, and if either key is a token - * object, the other must be too. + * We require a key size, and if either key is a token object, the + * other must be too. */ - if (id == NULL || id_len == 0 || keysize == 0 || public_handle_flavor != private_handle_flavor) + if (keysize == 0 || public_handle_flavor != private_handle_flavor) return CKR_TEMPLATE_INCOMPLETE; /* - * If we got this far, create the PKCS #11 objects. + * Create the PKCS #11 objects and generate the keypair. */ - if (!sql_exec("BEGIN")) + if (!sql_exec("BEGIN") || + (public_handle = p11_object_create(session, public_handle_flavor, + pPublicKeyTemplate, ulPublicKeyAttributeCount, + &p11_descriptor_rsa_public_key, + pMechanism)) == CK_INVALID_HANDLE || + (private_handle = p11_object_create(session, private_handle_flavor, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + &p11_descriptor_rsa_private_key, + pMechanism)) == CK_INVALID_HANDLE || + !p11_attribute_get(public_handle, CKA_PUBLIC_EXPONENT, + public_exponent, &public_exponent_len, sizeof(public_exponent)) || + !hal_check(hal_rsa_key_gen(&key, keybuf, sizeof(keybuf), keysize, + public_exponent, public_exponent_len)) || + !p11_object_set_rsa_private_key(private_handle, key) || + !hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus))) || + !p11_attribute_set(public_handle, CKA_MODULUS, modulus, modulus_len) || + !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len)) lose(CKR_FUNCTION_FAILED); - public_handle = p11_object_create(session, public_handle_flavor, - pPublicKeyTemplate, ulPublicKeyAttributeCount, - &p11_descriptor_rsa_public_key, pMechanism); - - private_handle = p11_object_create(session, private_handle_flavor, - pPrivateKeyTemplate, ulPrivateKeyAttributeCount, - &p11_descriptor_rsa_private_key, pMechanism); - - if (public_handle == CK_INVALID_HANDLE || private_handle == CK_INVALID_HANDLE) - lose(CKR_FUNCTION_FAILED); - - /* - * Generate the keypair. - */ - - if (!p11_object_get_keyid(private_handle, keyid, sizeof(keyid)) || - cryptlib_create_context(&ctx, CRYPT_ALGO_RSA) != CRYPT_OK || - cryptSetAttributeString(ctx, CRYPT_CTXINFO_LABEL, keyid, strlen(keyid)) != CRYPT_OK || - cryptSetAttribute(ctx, CRYPT_CTXINFO_KEYSIZE, keysize / 8) != CRYPT_OK || - cryptGenerateKey(ctx) != CRYPT_OK || - !p11_object_add_spki(public_handle, private_handle, ctx, p11_object_add_spki_rsa) || - cryptlib_store_key(ctx) != CRYPT_OK || - cryptDestroyContext(ctx) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + hal_rsa_key_clear(key); /* * Commit the SQL transaction. @@ -2425,11 +1932,7 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, fail: - if (ctx != CRYPT_HANDLE_NONE) - cryptDestroyContext(ctx); - - if (ctx != CRYPT_HANDLE_NONE && keyid[0] != 0x00) - (void) cryptlib_delete_key(keyid); + memset(keybuf, 0, sizeof(keybuf)); if (!sql_exec("ROLLBACK")) rv = CKR_GENERAL_ERROR; @@ -2437,6 +1940,54 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, return rv; } +/* + * Sign a PKCS #1 DigestInfo using an RSA key and PKCS #1.5 padding. + * + * As explained in RFC 3447, the RSASP1 (signature generation) + * operation is the same mathematical operation as the RSADP + * (decryption) operation (both use the private key as exponent). + */ + +static CK_RV sign_rsa_pkcs(hal_rsa_key_t key, + const uint8_t * const digest_info, const size_t digest_info_len, + uint8_t *signature, const size_t signature_len) +{ + CK_RV rv; + + assert(digest_info != NULL && signature != NULL); + + /* + * Congregation will now please turn to RFC 2313 8.1 as we + * construct a PKCS #1.5 type 01 encryption block. + */ + + if (digest_info_len > signature_len - 11) + lose(CKR_DATA_LEN_RANGE); + + signature[0] = 0x00; + signature[1] = 0x01; + memset(signature + 2, 0xFF, signature_len - 3 - digest_info_len); + signature[signature_len - digest_info_len - 1] = 0x00; + memcpy(signature + signature_len - digest_info_len, digest_info, digest_info_len); + +#if 0 + fprintf(stderr, "[PKCS #1.5 signature_len %lu digest_info_len %lu block ", signature_len, digest_info_len); + for (int i = 0; i < signature_len; i++) + fprintf(stderr, "%s%02x", i == 0 ? "" : ":", signature[i]); + fprintf(stderr, "]\n"); +#endif + + if (!hal_check(hal_rsa_decrypt(key, signature, signature_len, signature, signature_len))) + lose(CKR_FUNCTION_FAILED); + + return CKR_OK; + + fail: + memset(signature, 0, signature_len); + return rv; +} + + /* @@ -2445,8 +1996,8 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, CK_RV C_Initialize(CK_VOID_PTR pInitArgs) { - int initialized_sql = 0, initialized_cryptlib = 0; CK_C_INITIALIZE_ARGS_PTR a = pInitArgs; + int initialized_sql = 0; CK_RV rv; /* @@ -2549,27 +2100,9 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) initialized_sql = 1; - /* - * Initialize cryptlib and open the hardware crypto device (our FPGA). - * - * The option settings are to make sure that internal stuff like the - * PKCS #15 keyset code uses algorithms we like. - */ - - if (cryptInit() != CRYPT_OK) - lose(CKR_GENERAL_ERROR); - - initialized_cryptlib = 1; - - if (cryptSetAttribute(CRYPT_UNUSED, CRYPT_OPTION_ENCR_ALGO, CRYPT_ALGO_AES) != CRYPT_OK || - cryptSetAttribute(CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, CRYPT_ALGO_SHA2) != CRYPT_OK) + if (!kek_init()) lose(CKR_GENERAL_ERROR); -#if ENABLE_CRYPTLIB_DEVICE - if (cryptDeviceOpen(&cryptlib_device, CRYPT_UNUSED, CRYPT_DEVICE_HARDWARE, NULL) != CRYPT_OK) - lose(CKR_GENERAL_ERROR); -#endif - #if USE_POSIX initialized_pid = getpid(); #endif @@ -2578,16 +2111,6 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) fail: -#if ENABLE_CRYPTLIB_DEVICE - if (cryptlib_device != CRYPT_HANDLE_NONE) { - cryptDeviceClose(cryptlib_device); - cryptlib_device = CRYPT_HANDLE_NONE; - } -#endif - - if (initialized_cryptlib) - cryptEnd(); - if (initialized_sql) sql_fini(); @@ -2617,19 +2140,6 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved) lose(CKR_GENERAL_ERROR); /* - * Shut down hardware device and exit cryptlib. Is there any point - * in checking error codes here? - */ - -#if ENABLE_CRYPTLIB_DEVICE - if (cryptlib_device != CRYPT_HANDLE_NONE) - cryptDeviceClose(cryptlib_device); - cryptlib_device = CRYPT_HANDLE_NONE; -#endif - - cryptEnd(); - - /* * By this point we're pretty well committed to shutting down, so * there's not much to be done if these mutex operations fail. */ @@ -2873,9 +2383,13 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { + static const char pin_query_format[] = + " SELECT pbkdf2_iterations, %s_pin, %s_pin_salt from global"; + p11_session_t *session; + sqlite3_stmt *q = NULL; + const char *pin_type; CK_RV rv = CKR_OK; - int crypt_cmd; mutex_lock_or_return_failure(p11_global_mutex); @@ -2892,20 +2406,6 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, lose(CKR_SESSION_HANDLE_INVALID); /* - * This is where the combination of pure-software and hardware - * starts to get confusing. See the CRYPT_DEVINFO_* attributes for - * the operations we can do during device setup (setting PINs, - * logging in using pins, etc). - * - * All fine, but behaves somewhat differently from the case where - * we're doing everything in software and using the PIN primarily as - * the encryption password for the PKCS #15 keyring. - * - * In the long run just want the hardware interface. This will - * require cleanup. - */ - - /* * We don't currently support re-login without an intervening * logout, so reject the login attempt if we're already logged in. */ @@ -2914,53 +2414,82 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, lose(CKR_USER_ALREADY_LOGGED_IN); /* + * Figure out which PIN we're checking. * We don't (yet?) support CKU_CONTEXT_SPECIFIC. - */ - - switch (userType) { - case CKU_USER: crypt_cmd = CRYPT_DEVINFO_AUTHENT_USER; break; - case CKU_SO: crypt_cmd = CRYPT_DEVINFO_AUTHENT_SUPERVISOR; break; - case CKU_CONTEXT_SPECIFIC: lose(CKR_OPERATION_NOT_INITIALIZED); - default: lose(CKR_USER_TYPE_INVALID); - } - - /* + * * Read-only SO is an illegal state, so reject the login attempt if * we have any read-only sessions and we're trying to log in as SO. */ - if (userType == CKU_SO) + switch (userType) { + case CKU_USER: + pin_type = "user"; + break; + case CKU_SO: for (session = p11_sessions; session != NULL; session = session->link) if (session->state == CKS_RO_PUBLIC_SESSION) lose(CKR_SESSION_READ_ONLY_EXISTS); + pin_type = "so"; + break; + case CKU_CONTEXT_SPECIFIC: + lose(CKR_OPERATION_NOT_INITIALIZED); + default: + lose(CKR_USER_TYPE_INVALID); + } /* - * Ask Cryptlib to log us in. We may need to examine cryptlib error - * return more closely than this. + * Look up the PIN and make sure it's set. + * + * Not obvious what error we should return if SO PIN isn't set, for + * now consider this state "locked" (because it hasn't been set yet). */ -#if ENABLE_CRYPTLIB_DEVICE - if (cryptSetAttributeString(cryptlib_device, crypt_cmd, pPin, ulPinLen) != CRYPT_OK) - lose(CKR_PIN_INCORRECT); -#endif + if (!sql_check_ok(sql_prepare(&q, pin_query_format, pin_type, pin_type)) || + !sql_check_row(sqlite3_step(q))) + lose(CKR_FUNCTION_FAILED); + + if (sqlite3_column_type(q, 1) == SQLITE_NULL || + sqlite3_column_type(q, 2) == SQLITE_NULL) { + switch (userType) { + case CKU_USER: + lose(CKR_USER_PIN_NOT_INITIALIZED); + case CKU_SO: + lose(CKR_PIN_LOCKED); + default: + lose(CKR_USER_TYPE_INVALID); + } + } + + /* + * Run PBKDF2 over the supplied PIN and compare results. + * + * Probably not really necessary to use constant-time string + * comparison, but it's harmless and cheap, so we might as well. + */ -#if ENABLE_CRYPTLIB_SOFTWARE { - char *newpin; - if (memchr(pPin, '\0', ulPinLen) != NULL) + const unsigned iterations = sqlite3_column_int(q, 0); + const uint8_t * const pin = sqlite3_column_blob(q, 1); + const uint8_t * const salt = sqlite3_column_blob(q, 2); + const size_t pin_len = sqlite3_column_bytes(q, 1); + const size_t salt_len = sqlite3_column_bytes(q, 2); + uint8_t pinbuf[pin_len]; + unsigned diff = 0; + + if (!hal_check(hal_pbkdf2(hal_hash_sha256, pPin, ulPinLen, salt, salt_len, + pinbuf, sizeof(pinbuf), iterations))) + lose(CKR_FUNCTION_FAILED); + + for (int i = 0; i < pin_len; i++) + diff |= pin[i] ^ pinbuf[i]; + + if (diff != 0) lose(CKR_PIN_INCORRECT); - if ((newpin = malloc(ulPinLen + 1)) == NULL) - lose(CKR_HOST_MEMORY); - memcpy(newpin, pPin, ulPinLen); - newpin[ulPinLen] = '\0'; - if (pin != NULL) - free(pin); - pin = newpin; } -#endif /* - * Update global login state, then whack each session into correct new state. + * If we get here, the PIN was OK. Update global login state, then + * whack every session into the correct new state. */ assert(p11_session_consistent_login()); @@ -2985,6 +2514,7 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, assert(p11_session_consistent_login()); fail: + sqlite3_finalize(q); mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -2992,7 +2522,6 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) { p11_session_t *session; CK_RV rv = CKR_OK; - int crypt_cmd; mutex_lock_or_return_failure(p11_global_mutex); @@ -3005,31 +2534,8 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) if (p11_session_find(hSession) == NULL) lose(CKR_SESSION_HANDLE_INVALID); - switch (logged_in_as) { - case logged_in_as_user: crypt_cmd = CRYPT_DEVINFO_AUTHENT_USER; break; - case logged_in_as_so: crypt_cmd = CRYPT_DEVINFO_AUTHENT_SUPERVISOR; break; - case not_logged_in: lose(CKR_USER_NOT_LOGGED_IN); - } - - /* - * This is a bit problematic, because Cryptlib doesn't have a logout - * function per se. For lack of a better idea, construe logout as a - * new authentication attempt with an empty PIN. This is a little - * weird, but at least it's something we can use as a relatively - * clear signal to the HAL, and it's consistent with the way - * cryptlib does things like terminating digest inputs. - */ - -#if ENABLE_CRYPTLIB_DEVICE - if (cryptSetAttributeString(cryptlib_device, crypt_cmd, "", 0) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); -#endif - -#if ENABLE_CRYPTLIB_SOFTWARE - if (pin != NULL) - free(pin); - pin = NULL; -#endif + if (logged_in_as == not_logged_in) + lose(CKR_USER_NOT_LOGGED_IN); /* * Update global login state, then delete any private objects and @@ -3066,20 +2572,16 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { - static const char select_format[] = - " SELECT %s_object_id, keyid FROM object NATURAL JOIN %s_object WHERE object_handle = ?1"; - static const char delete_object[] = " DELETE FROM object WHERE object_handle = ?"; static const char delete_token_object[] = - " DELETE FROM token_object WHERE token_object_id = ?"; - - const char *flavor = is_token_handle(hObject) ? "token" : "session"; + " WITH" + " t AS (SELECT token_object_id FROM object WHERE object_handle = ?)" + " DELETE FROM token_object WHERE token_object_id = t"; p11_session_t *session; sqlite3_stmt *q = NULL; - sqlite3_int64 id; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3089,39 +2591,15 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, if ((rv = p11_object_check_rights(session, hObject, p11_object_access_write)) != CKR_OK) goto fail; - if (!sql_check_ok(sql_prepare(&q, select_format, flavor, flavor)) || - !sql_check_ok(sqlite3_bind_int64(q, 1, hObject))) - lose(CKR_FUNCTION_FAILED); - - switch (sqlite3_step(q)) { - case SQLITE_ROW: - break; - case SQLITE_DONE: - lose(CKR_OBJECT_HANDLE_INVALID); - default: - sql_whine_step(); - lose(CKR_FUNCTION_FAILED); - } - - id = sqlite3_column_int64(q, 0); - - if (sqlite3_column_type(q, 1) == SQLITE_TEXT && - cryptlib_delete_key((const char *) sqlite3_column_text(q, 1)) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - sqlite3_finalize(q); - q = NULL; - if (is_token_handle(hObject) && (!sql_check_ok(sql_prepare(&q, delete_token_object)) || - !sql_check_ok(sqlite3_bind_int64(q, 1, id)) || - !sql_check_done(sqlite3_step(q)))) + !sql_check_ok(sqlite3_bind_int64(q, 1, hObject)) || + !sql_check_done(sqlite3_step(q)) || + !sql_check_ok(sql_finalize_and_clear(&q)))) lose(CKR_FUNCTION_FAILED); - sqlite3_finalize(q); - q = NULL; - - if (!sql_check_ok(sql_prepare(&q, delete_object)) || + if ( + !sql_check_ok(sql_prepare(&q, delete_object)) || !sql_check_ok(sqlite3_bind_int64(q, 1, hObject)) || !sql_check_done(sqlite3_step(q))) lose(CKR_FUNCTION_FAILED); @@ -3300,10 +2778,6 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, lose(CKR_FUNCTION_FAILED); } - sqlite3_finalize(q1); - sqlite3_finalize(q2); - q1 = q2 = NULL; - /* * Create a temporary table to hold this session's FindObjects * state. Populate this with every object this session knows about, @@ -3311,27 +2785,30 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, * the caller supplied. */ - if (!sql_check_ok(sql_prepare(&q1, drop_format, hSession)) || + if (!sql_check_ok(sql_finalize_and_clear(&q1)) || + !sql_check_ok(sql_finalize_and_clear(&q2)) || + !sql_check_ok(sql_prepare(&q1, drop_format, hSession)) || !sql_check_done(sqlite3_step(q1)) || !sql_check_ok(sql_prepare(&q2, create_format, hSession)) || !sql_check_ok(sqlite3_bind_int64(q2, 1, hSession)) || - !sql_check_done(sqlite3_step(q2))) - lose(CKR_FUNCTION_FAILED); - - sqlite3_finalize(q1); - sqlite3_finalize(q2); - q1 = q2 = NULL; - - if (!sql_check_ok(sql_prepare(&q1, delete_format, hSession))) + !sql_check_done(sqlite3_step(q2)) || + !sql_check_ok(sql_finalize_and_clear(&q1)) || + !sql_check_ok(sql_finalize_and_clear(&q2)) || + !sql_check_ok(sql_prepare(&q1, delete_format, hSession))) lose(CKR_FUNCTION_FAILED); /* - * We only see private objects when logged in as the regular user. + * If we're not logged in as the regular user, run an extra filter + * cycle to remove all private objects before we get to the + * caller-supplied template. */ if (logged_in_as != logged_in_as_user) { - if (!sql_check_ok(sqlite3_bind_int64(q1, 1, CKA_PRIVATE)) || - !sql_check_ok(sqlite3_bind_blob(q1, 2, &const_CK_FALSE, sizeof(const_CK_FALSE), NULL)) || + if (!sql_check_ok(sqlite3_bind_int64(q1, 1, CKA_PRIVATE)) || + !sql_check_ok(sqlite3_bind_blob( q1, 2, + &const_CK_FALSE, + sizeof(const_CK_FALSE), + NULL)) || !sql_check_done(sqlite3_step(q1))) lose(CKR_FUNCTION_FAILED); } @@ -3441,10 +2918,8 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) * Clean up result query and temporary table. */ - sqlite3_finalize(session->find_query); - session->find_query = NULL; - - if (!sql_check_ok(sql_prepare(&q, drop_format, hSession)) || + if (!sql_check_ok(sql_finalize_and_clear(&session->find_query)) || + !sql_check_ok(sql_prepare(&q, drop_format, hSession)) || !sql_check_done(sqlite3_step(q))) lose(CKR_FUNCTION_FAILED); @@ -3457,8 +2932,6 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) { p11_session_t *session; - CRYPT_ALGO_TYPE algo; - unsigned hash_len = 0; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3469,33 +2942,25 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, if (pMechanism == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->digest_context != CRYPT_HANDLE_NONE) + if (session->digest_descriptor != NULL) lose(CKR_OPERATION_ACTIVE); switch (pMechanism->mechanism) { - case CKM_SHA_1: algo = CRYPT_ALGO_SHA1; break; - case CKM_SHA256: algo = CRYPT_ALGO_SHA2; hash_len = 256; break; - case CKM_SHA384: algo = CRYPT_ALGO_SHA2; hash_len = 384; break; - case CKM_SHA512: algo = CRYPT_ALGO_SHA2; hash_len = 512; break; + case CKM_SHA_1: session->digest_descriptor = hal_hash_sha1; break; + case CKM_SHA256: session->digest_descriptor = hal_hash_sha256; break; + case CKM_SHA384: session->digest_descriptor = hal_hash_sha384; break; + case CKM_SHA512: session->digest_descriptor = hal_hash_sha512; break; default: lose(CKR_MECHANISM_INVALID); } - assert((hash_len & 7) == 0); - - if (cryptlib_create_context(&session->digest_context, algo) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - if (algo == CRYPT_ALGO_SHA2 && - cryptSetAttribute(session->digest_context, CRYPT_CTXINFO_BLOCKSIZE, hash_len >> 3) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + if (!hal_check(hal_hash_core_present(session->digest_descriptor))) { + session->digest_descriptor = NULL; + lose(CKR_MECHANISM_INVALID); + } return mutex_unlock(p11_global_mutex); fail: - if (session != NULL && session->digest_context != CRYPT_HANDLE_NONE) { - cryptDestroyContext(session->digest_context); - session->digest_context = CRYPT_HANDLE_NONE; - } mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3507,7 +2972,6 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, { p11_session_t *session; CK_RV rv = CKR_OK; - int len; mutex_lock_or_return_failure(p11_global_mutex); @@ -3517,43 +2981,35 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, if (pData == NULL || pulDigestLen == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->digest_context == CRYPT_HANDLE_NONE) + if (session->digest_descriptor == NULL) lose(CKR_OPERATION_NOT_INITIALIZED); - if (pDigest == NULL) { - if (cryptGetAttribute(session->digest_context, CRYPT_CTXINFO_BLOCKSIZE, &len) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - *pulDigestLen = len; - return mutex_unlock(p11_global_mutex); - } - - if (cryptEncrypt(session->digest_context, pData, ulDataLen) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK; - if (ulDataLen != 0 && - cryptEncrypt(session->digest_context, pData, 0) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + *pulDigestLen = session->digest_descriptor->digest_length; - if (cryptGetAttributeString(session->digest_context, - CRYPT_CTXINFO_HASHVALUE, NULL, &len) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + if (pDigest == NULL) + return mutex_unlock(p11_global_mutex); - if (len > *pulDigestLen) + if (rv == CKR_BUFFER_TOO_SMALL) lose(CKR_BUFFER_TOO_SMALL); - if (cryptGetAttributeString(session->digest_context, - CRYPT_CTXINFO_HASHVALUE, pDigest, &len) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + { + uint8_t statebuf[session->digest_descriptor->hash_state_length]; + hal_hash_state_t state = { NULL }; - *pulDigestLen = len; + if (!hal_check(hal_hash_initialize(session->digest_descriptor, + &state, statebuf, sizeof(statebuf))) || + !hal_check(hal_hash_update(state, pData, ulDataLen)) || + !hal_check(hal_hash_finalize(state, pDigest, *pulDigestLen))) + lose(CKR_FUNCTION_FAILED); + } rv = CKR_OK; /* Fall through */ fail: - if (session != NULL && session->digest_context != CRYPT_HANDLE_NONE) { - cryptDestroyContext(session->digest_context); - session->digest_context = CRYPT_HANDLE_NONE; - } + if (session != NULL) + session->digest_descriptor = NULL; mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3562,11 +3018,6 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { p11_session_t *session; - char keyid[CRYPT_MAX_HASHSIZE * 2 + 1]; - CRYPT_ALGO_TYPE sign_algo, hash_algo; - unsigned hash_size = 0; - int need_cleanup = 0; - int key_algo; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3577,60 +3028,35 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, if (pMechanism == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->sign_key_context != CRYPT_HANDLE_NONE || - session->sign_digest_context != CRYPT_HANDLE_NONE) + if (session->sign_key_handle != CK_INVALID_HANDLE || session->sign_digest_descriptor != NULL) lose(CKR_OPERATION_ACTIVE); if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK) goto fail; + /* + * Will need to check key algorithm type here once we add support + * for signature algorithms other than RSA. + */ + + session->sign_key_handle = hKey; + switch (pMechanism->mechanism) { - case CKM_RSA_PKCS: sign_algo = CRYPT_ALGO_RSA; hash_algo = CRYPT_ALGO_NONE; break; - case CKM_SHA1_RSA_PKCS: sign_algo = CRYPT_ALGO_RSA; hash_algo = CRYPT_ALGO_SHA1; break; - case CKM_SHA256_RSA_PKCS: sign_algo = CRYPT_ALGO_RSA; hash_algo = CRYPT_ALGO_SHA2; hash_size = 256; break; - case CKM_SHA384_RSA_PKCS: sign_algo = CRYPT_ALGO_RSA; hash_algo = CRYPT_ALGO_SHA2; hash_size = 384; break; - case CKM_SHA512_RSA_PKCS: sign_algo = CRYPT_ALGO_RSA; hash_algo = CRYPT_ALGO_SHA2; hash_size = 512; break; + case CKM_RSA_PKCS: session->sign_digest_descriptor = NULL; break; + case CKM_SHA1_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha1; break; + case CKM_SHA256_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha256; break; + case CKM_SHA384_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha384; break; + case CKM_SHA512_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha512; break; default: return CKR_MECHANISM_INVALID; } - assert((hash_size & 7) == 0); - - need_cleanup = 1; - - if (!p11_object_get_keyid(hKey, keyid, sizeof(keyid)) || - cryptlib_load_key(&session->sign_key_context, keyid) != CRYPT_OK || - cryptGetAttribute(session->sign_key_context, CRYPT_CTXINFO_ALGO, &key_algo) != CRYPT_OK) - lose(CKR_KEY_HANDLE_INVALID); - - if (sign_algo != key_algo) - lose(CKR_KEY_TYPE_INCONSISTENT); - - if (hash_algo != CRYPT_ALGO_NONE && - cryptlib_create_context(&session->sign_digest_context, hash_algo) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - if (hash_algo == CRYPT_ALGO_SHA2 && - cryptSetAttribute(session->sign_digest_context, - CRYPT_CTXINFO_BLOCKSIZE, hash_size >> 3) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - need_cleanup = 0; - - rv = CKR_OK; /* Fall through */ + return mutex_unlock(p11_global_mutex); fail: - assert(!need_cleanup || session != NULL); - - if (need_cleanup && session->sign_key_context != CRYPT_HANDLE_NONE) { - cryptDestroyContext(session->sign_key_context); - session->sign_key_context = CRYPT_HANDLE_NONE; - } - - if (need_cleanup && session->sign_digest_context != CRYPT_HANDLE_NONE) { - cryptDestroyContext(session->sign_digest_context); - session->sign_digest_context = CRYPT_HANDLE_NONE; + if (session != NULL) { + session->sign_key_handle = CK_INVALID_HANDLE; + session->sign_digest_descriptor = NULL; } - mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3640,8 +3066,10 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { + uint8_t keybuf[hal_rsa_key_t_size]; + hal_rsa_key_t key = { NULL }; p11_session_t *session; - int len, algo; + size_t signature_len; CK_RV rv; mutex_lock_or_return_failure(p11_global_mutex); @@ -3652,160 +3080,111 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, if (pData == NULL || pulSignatureLen == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->sign_key_context == CRYPT_HANDLE_NONE) + if (session->sign_key_handle == CK_INVALID_HANDLE) lose(CKR_OPERATION_NOT_INITIALIZED); - if (pSignature == NULL) { - /* - * Caller just wants to know the signature length, which we can - * get from cryptCreateSignature(), using a dummy hash context if - * necessary. - * - * There may be an easier way: at least for RSA, reading the key's - * CRYPT_CTXINFO_KEYSIZE would give us the answer. But the - * constraint that messages_size == key_size doesn't necessarily - * hold for all asymmetric algorithms, so best to be safe here. - */ - - CRYPT_CONTEXT ctx = session->sign_digest_context; - - if (ctx == CRYPT_HANDLE_NONE && cryptCreateContext(&ctx, CRYPT_UNUSED, CRYPT_ALGO_SHA2) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - if (cryptCreateSignature(NULL, 0, &len, session->sign_key_context, ctx) != CRYPT_OK) - len = 0; + /* + * From here down this function is RSA-specific, and will need + * rewriting when we add support for other algorithms. + */ - if (session->sign_digest_context == CRYPT_HANDLE_NONE) - cryptDestroyContext(ctx); + if (!p11_object_get_rsa_private_key(session->sign_key_handle, + &key, keybuf, sizeof(keybuf))) + lose(CKR_FUNCTION_FAILED); - if (len == 0) - lose(CKR_FUNCTION_FAILED); - } + /* + * Retrieve signature length. For RSA this is just the modulus + * length, other algorithms will need a more generic solution. + */ - else if (session->sign_digest_context != CRYPT_HANDLE_NONE) { - /* - * Caller wanted a hash-and-sign operation, so we can use cryptCreateSignature(). - */ + if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &signature_len, 0))) + lose(CKR_FUNCTION_FAILED); - if (cryptEncrypt(session->sign_digest_context, pData, ulDataLen) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + rv = signature_len > *pulSignatureLen ? CKR_BUFFER_TOO_SMALL : CKR_OK; - if (ulDataLen != 0 && - cryptEncrypt(session->sign_digest_context, pData, 0) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + *pulSignatureLen = signature_len; - if (cryptCreateSignature(pSignature, *pulSignatureLen, &len, - session->sign_key_context, - session->sign_digest_context) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + if (pSignature == NULL) { + hal_rsa_key_clear(key); + return mutex_unlock(p11_global_mutex); } - else { + if (rv == CKR_BUFFER_TOO_SMALL) + lose(CKR_BUFFER_TOO_SMALL); + if (session->sign_digest_descriptor != NULL) { /* - * Caller wanted a pure-signature operation, have to use - * cryptDeCrypt() [sic]. + * Caller wanted a hash-and-sign operation. We need to hash the + * caller's data and construct a DigestInfo SEQUENCE. * - * At the moment we just blindly sign this without checking that - * what we're signing really is (eg) a valid DigestInfo SEQUENCE. - * Should we bother checking the syntax here, given that we have - * no way of checking the digest itself (if we get here, we've - * never seen the original plaintext, just the purported digest)? + * This probably ought to be a library function somewhere. */ - if (cryptGetAttribute(session->sign_key_context, CRYPT_CTXINFO_ALGO, &algo) != CRYPT_OK || - cryptGetAttribute(session->sign_key_context, CRYPT_CTXINFO_KEYSIZE, &len) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); - - switch (algo) { - - case CRYPT_ALGO_RSA: - - /* - * Congregation will now please turn to RFC 2313 8.1 as we - * construct a PKCS #1.5 type 01 encryption block. - */ + const hal_hash_descriptor_t *desc = session->sign_digest_descriptor; + uint8_t digest_info[desc->digest_length + desc->digest_algorithm_id_length + 4]; + uint8_t statebuf[session->digest_descriptor->hash_state_length]; + hal_hash_state_t state = { NULL }; + uint8_t *d = digest_info; - if (len > *pulSignatureLen) - lose(CKR_BUFFER_TOO_SMALL); + /* + * This encoder will fail if the DigestInfo object is more than + * 129 octets long. Rewrite if and when we need to support + * digests or OIDs long enough for that to be an issue. + */ + assert(sizeof(digest_info) < 130); - if (ulDataLen > len - 11) - return CKR_DATA_LEN_RANGE; + *d++ = 0x30; /* SEQUENCE */ + *d++ = (uint8_t) (sizeof(digest_info) - 2); - pSignature[0] = 0x00; - pSignature[1] = 0x01; - memset(pSignature + 2, 0xFF, len - 3 - ulDataLen); - pSignature[len - ulDataLen - 1] = 0x00; - memcpy(pSignature + len - ulDataLen, pData, ulDataLen); + memcpy(d, desc->digest_algorithm_id, desc->digest_algorithm_id_length); + d += desc->digest_algorithm_id_length; -#if 0 - /* XXX */ - { - int i; - fprintf(stderr, "[PKCS #1.5 len %lu ulDataLen %lu block ", len, ulDataLen); - for (i = 0; i < len; i++) - fprintf(stderr, "%s%02x", i == 0 ? "" : ":", pSignature[i]); - fprintf(stderr, "]\n"); - } -#endif + *d++ = 0x04; /* OCTET STRING */ + *d++ = (uint8_t) desc->digest_length; - break; + assert(digest_info + sizeof(digest_info) == d + desc->digest_length); - default: + if (!hal_check(hal_hash_initialize(desc, &state, statebuf, sizeof(statebuf))) || + !hal_check(hal_hash_update(state, pData, ulDataLen)) || + !hal_check(hal_hash_finalize(state, d, desc->digest_length))) { + memset(digest_info, 0, sizeof(digest_info)); lose(CKR_FUNCTION_FAILED); } + rv = sign_rsa_pkcs(key, digest_info, sizeof(digest_info), pSignature, signature_len); + memset(digest_info, 0, sizeof(digest_info)); + if (rv != CKR_OK) + goto fail; + } + + else { + /* - * The terms "encrypt" and "decrypt" get weird when one goes this - * far past the API that a sane person would be using. As - * explained in RFC 3447, the RSASP1 (signature generation) - * operation is the same mathematical operation as the RSADP - * (decryption) operation, so we have to use cryptDecrypt(), not - * cryptEncrypt() here. No, really. - * - * Well, this works for RSA, anyway. ECDSA may turn out to be a - * whole different bucket of monkey guts. + * Caller wanted a pure-signature operation. We assume that input + * is a valid DigestInfo SEQUENCE: we've never seen the original + * plaintext, thus can't check the hash, so there's not much point + * in checking the ASN.1 structure. */ - if (cryptDecrypt(session->sign_key_context, pSignature, len) != CRYPT_OK) - lose(CKR_FUNCTION_FAILED); + if ((rv = sign_rsa_pkcs(key, pData, ulDataLen, pSignature, signature_len)) != CKR_OK) + goto fail; } - *pulSignatureLen = len; - rv = CKR_OK; /* Fall through */ fail: - if (session != NULL && session->sign_digest_context != CRYPT_HANDLE_NONE) { - cryptDestroyContext(session->sign_digest_context); - session->sign_digest_context = CRYPT_HANDLE_NONE; + if (session != NULL) { + session->sign_key_handle = CK_INVALID_HANDLE; + session->sign_digest_descriptor = NULL; } - if (session != NULL && session->sign_key_context != CRYPT_HANDLE_NONE) { - cryptDestroyContext(session->sign_key_context); - session->sign_key_context = CRYPT_HANDLE_NONE; - } + hal_rsa_key_clear(key); mutex_unlock_return_with_rv(rv, p11_global_mutex); } /* - * libhsm only uses C_GenerateKey() for DSA parameter generation. - * More general use presumably wants this for things like generating - * symmetric keys for later wrapping by asymmetric keys. - */ - -CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phKey) -{ - return CKR_FUNCTION_NOT_SUPPORTED; -} - -/* * If there's any method in this entire package which really needs a * more complex mutex structure than the single global mutex, it's * probably this one. Key generation can take a looooong time. @@ -3856,7 +3235,6 @@ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_ULONG ulRandomLen) { p11_session_t *session; - CRYPT_CONTEXT ctx = CRYPT_HANDLE_NONE; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3867,25 +3245,10 @@ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, if (RandomData == NULL) lose(CKR_ARGUMENTS_BAD); - /* - * Cryptlib doesn't expose the raw TRNG, but, per the manual, block - * cipher encryption output with a randomly generated key is good - * enough for most sane purposes. - * - * Not certain why the Cryptlib manual suggests using CFB mode - * instead of OFB mode here, but going with the manual for now. - */ - - if (cryptCreateContext(&ctx, CRYPT_UNUSED, CRYPT_ALGO_AES) != CRYPT_OK || - cryptSetAttribute(ctx, CRYPT_CTXINFO_MODE, CRYPT_MODE_CFB) != CRYPT_OK || - cryptGenerateKey(ctx) != CRYPT_OK || - cryptEncrypt(ctx, RandomData, ulRandomLen) != CRYPT_OK) + if (!hal_check(hal_get_random(RandomData, ulRandomLen))) lose(CKR_FUNCTION_FAILED); fail: - if (ctx != CRYPT_HANDLE_NONE) - (void) cryptDestroyContext(ctx); - mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3904,6 +3267,13 @@ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, * there are enough bald yaks in this saga already. */ +CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey) +{ return CKR_FUNCTION_NOT_SUPPORTED; } + CK_RV C_GetInfo(CK_INFO_PTR pInfo) { return CKR_FUNCTION_NOT_SUPPORTED; } @@ -51,6 +51,55 @@ PRAGMA foreign_keys = ON; +-- Values we have to store somewhere and for which we have no better +-- place. This is a table with exactly one row (enforced by the CHECK +-- clause on the primary index). All columns must either allow NULL +-- or provide default values. + +CREATE TABLE IF NOT EXISTS global ( + global_id INTEGER PRIMARY KEY NOT NULL DEFAULT 1 CHECK (global_id = 1), + + -- Key-encryption-key (KEK) + -- + -- The KEK **really** should be somewhere else, like in RAM + -- protected by tamper detection circuitry, but we don't have + -- that yet. Not obvious that a separate file would be more + -- secure, so keep it here until we do have a better place. + + kek BLOB CHECK (kek IS NULL OR (typeof(kek) = "blob" AND length(kek) IN (16, 32))), + + -- PBKDF2-based PIN storage and check values. + -- + -- "so_pin" and "user_pin" are PBKDF2 output, so only + -- moderately sensitive. + -- + -- Not obvious that PKCS #11 ever really allows "so_pin" to be + -- unset, so it may want a NOT NULL constraint, but in that + -- case we'll need to provide a default value, which doesn't + -- seem like much of an improvement. "so_pin" probably + -- requires out-of-band initialization. "user-pin" is allowed + -- to be unset, there's an error code specifically for that + -- situation. + -- + -- Numeric minima for PBKDF2 iterations, length of PIN, and + -- length of PBKDF2 salt are somewhat arbitrary, and will + -- probably change over time (which is why they are minima). + -- Feel free to suggest better minima. + + pbkdf2_iterations INTEGER NOT NULL DEFAULT 100000, + so_pin BLOB, + user_pin BLOB, + so_pin_salt, BLOB, + user_pin_salt BLOB, + CHECK ((pbkdf2_iterations >= 100000) AND + (so_pin IS NULL OR (typeof(so_pin) = "blob" AND length(so_pin) >= 32)) AND + (user_pin IS NULL OR (typeof(user_pin) = "blob" AND length(user_pin) >= 32)) AND + (so_pin_salt IS NULL OR (typeof(so_pin_salt) = "blob" AND length(so_pin_salt) >= 16)) AND + (user_pin_salt IS NULL OR (typeof(user_pin_salt) = "blob" AND length(user_pin_salt) >= 16))) +); + +INSERT OR IGNORE INTO global DEFAULT VALUES; + CREATE TEMPORARY TABLE IF NOT EXISTS session ( session_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, session_handle INTEGER NOT NULL UNIQUE @@ -75,7 +124,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS object ( CREATE TEMPORARY TABLE IF NOT EXISTS session_object ( session_object_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - keyid TEXT UNIQUE, + private_key BLOB UNIQUE, object_id INTEGER NOT NULL UNIQUE REFERENCES object ON DELETE CASCADE ON UPDATE CASCADE @@ -92,7 +141,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS session_attribute ( CREATE TABLE IF NOT EXISTS token_object ( token_object_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - keyid TEXT UNIQUE + private_key BLOB UNIQUE ); CREATE TABLE IF NOT EXISTS token_attribute ( |