summaryrefslogtreecommitdiffstats
path: root/nss_engine_pcache.c
diff options
context:
space:
mode:
authorrcritten <>2005-05-17 14:50:16 +0000
committerrcritten <>2005-05-17 14:50:16 +0000
commitf6ecd9df97f9bb1be9b69ae97a78eb54b6599463 (patch)
treec4c8e184503e99362268f59dfa8d3ce114c18013 /nss_engine_pcache.c
downloadmod_nss-f6ecd9df97f9bb1be9b69ae97a78eb54b6599463.tar.gz
mod_nss-f6ecd9df97f9bb1be9b69ae97a78eb54b6599463.tar.xz
mod_nss-f6ecd9df97f9bb1be9b69ae97a78eb54b6599463.zip
Initial import of mod_nss
Diffstat (limited to 'nss_engine_pcache.c')
-rw-r--r--nss_engine_pcache.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/nss_engine_pcache.c b/nss_engine_pcache.c
new file mode 100644
index 0000000..d32c753
--- /dev/null
+++ b/nss_engine_pcache.c
@@ -0,0 +1,295 @@
+/* Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mod_nss.h"
+
+/*
+ * Mechanisms for doing the PIN encryption. Each of these lists
+ * an encryption mechanism, with setup, encode and decode routines that
+ * use that mechanism. The PK11PinStore looks for a mechanism
+ * that the token supports, and then uses it. If none is found,
+ * it will fail.
+ */
+typedef struct mech_item mech_item;
+
+struct mech_item
+{
+ CK_MECHANISM_TYPE type;
+ const char *mechName;
+};
+
+/*
+ * The table listing all mechanism to try
+ */
+#define MECH_TABLE_SIZE 4
+static const mech_item table[MECH_TABLE_SIZE] = {
+ { CKM_SKIPJACK_CBC64, "Skipjack CBC-64 encryption" },
+ { CKM_DES3_CBC, "Triple-DES CBC encryption" },
+ { CKM_CAST128_CBC, "CAST-128 CBC encryption" },
+ { CKM_DES_CBC, "DES CBC encryption" }
+};
+
+static mech_item dflt_mech = { CKM_DES3_CBC, "Triple-DES CBC (default)" };
+
+/*
+ * Implementation
+ */
+struct Pk11PinStore
+{
+ char *tokenName;
+
+ mech_item *mech;
+
+ SECItem *key;
+ SECItem *params;
+
+ int length;
+ unsigned char *crypt;
+};
+
+/*
+ * CreatePk11PinStore
+ */
+SECStatus
+CreatePk11PinStore(apr_pool_t *pool, Pk11PinStore **out, const char *tokenName, const char *pin)
+{
+ SECStatus err;
+ Pk11PinStore *store;
+ PK11SymKey *tmpkey;
+ SECItem *tmpparams;
+ PK11SlotInfo *slot;
+
+ do {
+ err = SECSuccess;
+
+ store = (Pk11PinStore*)apr_pcalloc(pool, sizeof(Pk11PinStore));
+ if (store == 0) { err = SECFailure; break; }
+
+ /* Low-level init */
+ store->tokenName = 0;
+ store->key = 0;
+ store->params = 0;
+ store->crypt = 0;
+
+ store->mech = (mech_item *)apr_pcalloc(pool, sizeof(mech_item));
+
+ /* Use the tokenName to find a PKCS11 slot */
+ slot = PK11_FindSlotByName((char *)tokenName);
+ if (slot == 0) { err = SECFailure; break; }
+
+ /* Check the password/PIN. This allows access to the token */
+ {
+ SECStatus rv = PK11_CheckUserPassword(slot, (char *)pin);
+
+ if (rv == SECSuccess)
+ ;
+ else if (rv == SECWouldBlock)
+ {
+ err = SECFailure;
+ break;
+ }
+ else
+ {
+ err = SECFailure;
+ break;
+ }
+ }
+ store->tokenName = apr_pstrdup(pool, tokenName);
+
+ /* Find the mechanism that this token can do */
+ {
+ const mech_item *tp;
+
+ for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++)
+ {
+ if (PK11_DoesMechanism(slot, tp->type))
+ {
+// store->mech = tp;
+ store->mech->type = tp->type;
+ store->mech->mechName = apr_pstrdup(pool, tp->mechName);
+ break;
+ }
+ }
+ /* Default to a mechanism (probably on the internal token */
+ if (store->mech == 0) {
+// store->mech = &dflt_mech;
+ store->mech->type = dflt_mech.type;
+ store->mech->mechName = (char *)apr_pstrdup(pool, dflt_mech.mechName);
+ }
+ }
+
+ /* Generate a key and parameters to do the encryption */
+ tmpkey = PK11_KeyGen(slot, store->mech->type,
+ 0, 0, 0);
+ if (tmpkey == 0)
+ {
+ /* PR_SetError(xxx); */
+ err = SECFailure;
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "key failed %d", PR_GetError());
+ break;
+ }
+ {
+ SECItem *keydata = PK11_GetKeyData(tmpkey);
+
+ store->key = (SECItem *)apr_pcalloc(pool, sizeof(SECItem));
+ store->key->type = keydata->type;
+ store->key->len = keydata->len;
+ store->key->data = apr_pcalloc(pool, keydata->len);
+ memcpy(store->key->data, keydata->data, keydata->len);
+ if (SECITEM_CompareItem(store->key, keydata) != SECEqual)
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "key copy failed");
+ }
+
+ tmpparams = PK11_GenerateNewParam(store->mech->type, tmpkey);
+ if (tmpparams == 0)
+ {
+ err = SECFailure;
+ break;
+ }
+ store->params = (SECItem *)apr_pcalloc(pool, sizeof(SECItem));
+ store->params->len = tmpparams->len;
+ store->params->data = apr_pcalloc(pool, tmpparams->len);
+ store->params->type = tmpparams->type;
+ memcpy(store->params->data, tmpparams->data, tmpparams->len);
+ if (SECITEM_CompareItem(store->params, tmpparams) != SECEqual)
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "params copy failed");
+
+ /* Compute the size of the encrypted data including necessary padding */
+ {
+ int blocksize = PK11_GetBlockSize(store->mech->type, 0);
+
+ store->length = strlen(pin)+1;
+
+ /* Compute padded size - 0 means stream cipher */
+ if (blocksize != 0)
+ {
+ store->length += blocksize - (store->length % blocksize);
+ }
+
+ store->crypt = (unsigned char *)apr_pcalloc(pool, store->length);
+ if (!store->crypt) { err = SECFailure; break; }
+ }
+
+ /* Encrypt */
+ {
+ unsigned char *plain;
+ PK11Context *ctx;
+ SECStatus rv;
+ int outLen;
+
+ plain = (unsigned char *)malloc(store->length);
+ if (!plain) { err = SECFailure; break; }
+
+ /* Pad with 0 bytes */
+ memset(plain, 0, store->length);
+ strcpy((char *)plain, pin);
+
+ ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT,
+ tmpkey, store->params);
+ if (!ctx) { err = SECFailure; break; }
+
+ do {
+ rv = PK11_CipherOp(ctx, store->crypt, &outLen, store->length,
+ plain, store->length);
+ if (rv) break;
+
+ rv = PK11_Finalize(ctx);
+ } while(0);
+
+ PK11_DestroyContext(ctx, PR_TRUE);
+ memset(plain, 0, store->length);
+ free(plain);
+
+ if (rv) err = SECFailure;
+ }
+ } while(0);
+
+ if (err)
+ {
+ DestroyPk11PinStore(store);
+ store = 0;
+ }
+
+ *out = store;
+ return err;
+}
+
+/*
+ * DestroyPk11PinStore
+ */
+void DestroyPk11PinStore(Pk11PinStore *store)
+{
+ if (store == 0) return;
+
+ if (store->params) {
+ SECITEM_ZfreeItem(store->params, PR_TRUE);
+ }
+
+ if (store->crypt) {
+ memset(store->crypt, 0, store->length);
+ free(store->crypt);
+ }
+
+ free(store);
+}
+
+SECStatus Pk11StoreGetPin(char **out, Pk11PinStore *store)
+{
+ SECStatus err = SECSuccess;
+ unsigned char *plain;
+ SECStatus rv;
+ PK11Context *ctx = 0;
+ int outLen;
+ PK11SlotInfo *slot;
+ PK11SymKey * tmpkey;
+
+ do {
+ plain = (unsigned char *)malloc(store->length);
+ if (!plain) { err = SECFailure;ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "plain is null"); break; }
+
+ slot = PK11_FindSlotByName(store->tokenName);
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "slot is %s param len is %d", store->tokenName, store->params->len);
+ if (slot == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "no slot");
+ err=SECFailure;break;
+ }
+ tmpkey = PK11_KeyGen(slot, store->mech->type,
+ store->key, 0, 0);
+ ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_DECRYPT,
+ tmpkey, store->params);
+ if (!ctx) { err = SECFailure; ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "ctx is null %d", PR_GetError());break; }
+
+ rv = PK11_CipherOp(ctx, plain, &outLen, store->length,
+ store->crypt, store->length);
+ if (rv) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "cipherop failed");break; }
+
+ rv = PK11_Finalize(ctx);
+ if (rv) break;
+ } while(0);
+
+ if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
+
+ if (rv)
+ {
+ err = SECFailure;
+ memset(plain, 0, store->length);
+ free(plain);
+ plain = 0;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "plain is %s", plain);
+ *out = (char *)plain;
+ return err;
+}