TPS_PUBLIC PK11SymKey *Util::DiversifyKey(PK11SymKey *masterKey, Buffer &data, PK11SlotInfo *slot) { PK11SymKey *key = NULL; PRStatus status = PR_FAILURE ; PK11Context *context = NULL; #ifdef DES2_WORKAROUND unsigned char keyData[24]; #else unsigned char keyData[16]; #endif SECItem keyItem = { siBuffer, keyData, sizeof keyData }; SECStatus s; int i; int len; static SECItem noParams = { siBuffer, 0, 0 }; /* XXX - masterKey could be just a double-length DES Key (16 bytes). - we may need to add the first 8 bytes to the end to make the key 24 bytes long (DES3 Key) */ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, masterKey, &noParams); if (!context) goto done; /* Part 1 */ s = PK11_CipherOp(context, &keyData[0], &len, 8, &((BYTE*)data)[0], 8); if (s != SECSuccess) goto done; /* Part 2 */ s = PK11_CipherOp(context, &keyData[8], &len, 8, &((BYTE*)data)[8], 8); if (s != SECSuccess) goto done; #ifdef DES2_WORKAROUND /* Part 3 */ for(i = 0;i < 8;i++) { keyData[i+16] = keyData[i]; } #endif key = PK11_ImportSymKeyWithFlags( slot, CKM_DES3_ECB, PK11_OriginGenerated, CKA_ENCRYPT, &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0); status = PR_SUCCESS; done: return key; }
static void sipe_crypt_ctx_encrypt(PK11Context* EncContext, const guchar *in, gsize length, guchar *out) { int tmp1_outlen; PK11_CipherOp(EncContext, out, &tmp1_outlen, length, (unsigned char *)in, length); }
NS_IMETHODIMP nsStreamCipher::Discard(PRInt32 aLen) { if (!mContext) return NS_ERROR_NOT_INITIALIZED; unsigned char* output = new unsigned char[aLen]; if (!output) return NS_ERROR_OUT_OF_MEMORY; unsigned char* input = new unsigned char[aLen]; if (!input) { delete [] output; return NS_ERROR_OUT_OF_MEMORY; } PRInt32 setLen; #ifdef DEBUG SECStatus rv = #endif PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen); NS_ASSERTION(rv == SECSuccess, "failed to encrypt"); NS_ASSERTION(setLen == aLen, "data length should not change"); delete [] output; delete [] input; return NS_OK; }
NS_IMETHODIMP nsStreamCipher::Update(const PRUint8 *aData, PRUint32 aLen) { if (!mContext) return NS_ERROR_NOT_INITIALIZED; unsigned char* output = new unsigned char[aLen]; if (!output) return NS_ERROR_OUT_OF_MEMORY; unsigned char* input = (unsigned char*)aData; PRInt32 setLen; #ifdef DEBUG SECStatus rv = #endif PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen); NS_ASSERTION(rv == SECSuccess, "failed to encrypt"); NS_ASSERTION((PRUint32)setLen == aLen, "data length should not change"); mValue.Append((const char*)output, aLen); delete [] output; return NS_OK; }
NS_IMETHODIMP nsStreamCipher::UpdateFromString(const nsACString& aInput) { if (!mContext) return NS_ERROR_NOT_INITIALIZED; const nsCString& flatInput = PromiseFlatCString(aInput); unsigned char* input = (unsigned char*)flatInput.get(); PRUint32 len = aInput.Length(); unsigned char* output = new unsigned char[len]; if (!output) return NS_ERROR_OUT_OF_MEMORY; PRInt32 setLen; #ifdef DEBUG SECStatus rv = #endif PK11_CipherOp(mContext, output, &setLen, len, input, len); NS_ASSERTION(rv == SECSuccess, "failed to encrypt"); NS_ASSERTION((PRUint32)setLen == len, "data length should not change"); mValue.Append((const char*)output, len); delete [] output; return NS_OK; }
/* * for Secure Messaging in Secure Channel */ TPS_PUBLIC PRStatus Util::EncryptData(PK11SymKey *encSessionKey, Buffer &input, Buffer &output) { PRStatus rv = PR_FAILURE; SECStatus s = SECFailure; //static SECItem noParams = { siBuffer, 0, 0 }; static unsigned char d[8] = { 0,0,0,0,0,0,0,0 }; static SECItem ivParams = { siBuffer, d, 8 }; PK11Context *context = NULL; unsigned char result[8]; int len; int i; /* this is ECB mode context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, encSessionKey, &noParams); */ // use CBC mode context = PK11_CreateContextBySymKey(CKM_DES3_CBC, CKA_ENCRYPT, encSessionKey, &ivParams); if (!context) { goto done; } for(i = 0;i < (int)input.size();i += 8) { s = PK11_CipherOp(context, result, &len, 8, (unsigned char *)(((BYTE*)input)+i), 8); if (s != SECSuccess) { goto done; } output.replace(i, result, 8); } rv = PR_SUCCESS; // RA::Debug("Util::EncryptData", "success"); done: //#define VRFY_ENC_SESSION_KEY // fix this to use CBC mode later #ifdef VRFY_ENC_SESSION_KEY Buffer enc_key_buffer = Buffer((BYTE *) PK11_GetKeyData(encSessionKey)->data, PK11_GetKeyData(encSessionKey)->len); RA::DebugBuffer("Util::EncryptData", "Verifying Encrypted Data", &output); Buffer out1 = Buffer(16, (BYTE)0); PRStatus status = Util::DecryptData(enc_key_buffer, output, out1); RA::DebugBuffer("Util::EncryptData", "Decrypted Data", &out1); #endif if( context != NULL ) { PK11_DestroyContext( context, PR_TRUE ); context = NULL; } return rv; }
void crypto_rc4(CryptoRc4 rc4, uint32 len, uint8 * in_data, uint8 * out_data) { int outlen; /* valgrind "Invalid read"? See http://groups.google.com/group/mozilla.dev.tech.crypto/browse_thread/thread/361c017b4aa5226f/43badd163bef22f2 */ SECStatus s = PK11_CipherOp(rc4->context, out_data, &outlen, len, in_data, len); check(s, "Error in rc4 encryption"); ASSERT(outlen == len); }
static int decrypt_nss ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* decrypt_context = NULL; SECItem decrypt_param; int tmp1_outlen = 0; unsigned int tmp2_outlen = 0; unsigned char *salt = (unsigned char *)buf_in; unsigned char *data = salt + SALT_SIZE; int datalen = buf_in_len - SALT_SIZE; int err = -1; /* Create cipher context for decryption */ decrypt_param.type = siBuffer; decrypt_param.data = salt; decrypt_param.len = SALT_SIZE; decrypt_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type], CKA_DECRYPT, instance->nss_sym_key, &decrypt_param); if (!decrypt_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext (decrypt) failed (err %d)", PR_GetError()); goto out; } if (PK11_CipherOp(decrypt_context, buf_out, &tmp1_outlen, KNET_DATABUFSIZE_CRYPT, data, datalen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp (decrypt) failed (err %d)", PR_GetError()); goto out; } if (PK11_DigestFinal(decrypt_context, buf_out + tmp1_outlen, &tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal (decrypt) failed (err %d)", PR_GetError()); goto out; } *buf_out_len = tmp1_outlen + tmp2_outlen; err = 0; out: if (decrypt_context) { PK11_DestroyContext(decrypt_context, PR_TRUE); } return err; }
// this one takes PK11SymKey instead TPS_PUBLIC PRStatus Util::DecryptData(PK11SymKey* enc_key, Buffer &input, Buffer &output) { PRStatus rv = PR_FAILURE; PK11Context *context = NULL; int i; SECStatus s = SECFailure; int len; // static SECItem noParams = { siBuffer, 0, 0 }; static unsigned char d[8] = { 0,0,0,0,0,0,0,0 }; static SECItem ivParams = { siBuffer, d, 8 }; unsigned char result[8]; if( ! enc_key ) { goto done; } context = PK11_CreateContextBySymKey(CKM_DES3_CBC, CKA_DECRYPT, enc_key, &ivParams); if (!context) { goto done; } for(i = 0;i < (int)input.size();i += 8) { s = PK11_CipherOp(context, result, &len, 8, (unsigned char *)(((BYTE *)input)+i), 8); if (s != SECSuccess) { goto done; } output.replace(i, result, 8); } rv = PR_SUCCESS; done: if( context != NULL ) { PK11_DestroyContext( context, PR_TRUE ); context = NULL; } return rv; }
SVRCOREError SVRCORE_Pk11StoreGetPin(char **out, SVRCOREPk11PinStore *store) { SVRCOREError err = SVRCORE_Success; unsigned char *plain; SECStatus rv; PK11Context *ctx = 0; int outLen; do { plain = (unsigned char *)malloc(store->length); if (!plain) { err = SVRCORE_NoMemory_Error; break; } ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_DECRYPT, store->key, store->params); if (!ctx) { err = SVRCORE_System_Error; break; } rv = PK11_CipherOp(ctx, plain, &outLen, store->length, store->crypt, store->length); if (rv) break; rv = PK11_Finalize(ctx); if (rv) break; } while(0); if (ctx) PK11_DestroyContext(ctx, PR_TRUE); if (rv) { err = SVRCORE_System_Error; memset(plain, 0, store->length); free(plain); plain = 0; } *out = (char *)plain; return err; }
int Pk11StoreGetPin(char **out, Pk11PinStore *store) { int err = PIN_SUCCESS; unsigned char *plain; SECStatus rv = SECSuccess; PK11Context *ctx = 0; int outLen; do { plain = (unsigned char *)malloc(store->length); if (!plain) { err = PIN_NOMEMORY; break; } ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_DECRYPT, store->key, store->params); if (!ctx) { err = PIN_SYSTEMERROR; break; } rv = PK11_CipherOp(ctx, plain, &outLen, store->length, store->crypt, store->length); if (rv) break; rv = PK11_Finalize(ctx); if (rv) break; } while(0); if (ctx) PK11_DestroyContext(ctx, PR_TRUE); if (rv) { err = PIN_SYSTEMERROR; memset(plain, 0, store->length); free(plain); plain = 0; } *out = (char *)plain; return err; }
/** * @brief Decrypt data provided by in, write it to out. * @note The number of bytes written will be written to outlen. If * out is NULL, outlen will contain the maximum size of the * buffer needed to hold the data, including any data * generated by apr_crypto_block_decrypt_finish below. If *out points * to NULL, a buffer sufficiently large will be created from * the pool provided. If *out points to a not-NULL value, this * value will be used as a buffer instead. * @param out Address of a buffer to which data will be written, * see note. * @param outlen Length of the output will be written here. * @param in Address of the buffer to read. * @param inlen Length of the buffer to read. * @param ctx The block context to use. * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if * not implemented. */ static apr_status_t crypto_block_decrypt(unsigned char **out, apr_size_t *outlen, const unsigned char *in, apr_size_t inlen, apr_crypto_block_t *block) { unsigned char *buffer; int outl = (int) *outlen; SECStatus s; if (!out) { *outlen = inlen + block->blockSize; return APR_SUCCESS; } if (!*out) { buffer = apr_palloc(block->pool, inlen + block->blockSize); if (!buffer) { return APR_ENOMEM; } apr_crypto_clear(block->pool, buffer, inlen + block->blockSize); *out = buffer; } s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in, inlen); if (s != SECSuccess) { PRErrorCode perr = PORT_GetError(); if (perr) { block->f->result->rc = perr; block->f->result->msg = PR_ErrorToName(perr); } return APR_ECRYPT; } *outlen = outl; return APR_SUCCESS; }
size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res) { #define CIPHER_MECH CKM_DES3_CBC #define MAX_OUTPUT_LEN 72 int len1; unsigned int len2; PK11Context *ctx = NULL; PK11SlotInfo *slot = NULL; SECItem keyItem; SECItem ivItem; SECItem *secParam = NULL; PK11SymKey *symKey = NULL; size_t rc; SECStatus rv; if (!initialized) { ssl_init(); } keyItem.data = (unsigned char *)key; keyItem.len = key_len; slot = PK11_GetBestSlot(CIPHER_MECH, NULL); if (slot == NULL) { fprintf(stderr, "PK11_GetBestSlot failed (err %d)\n", PR_GetError()); rc = 0; goto out; } symKey = PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL); if (symKey == NULL) { fprintf(stderr, "PK11_ImportSymKey failed (err %d)\n", PR_GetError()); rc = 0; goto out; } ivItem.data = (unsigned char *)iv; /* See msn_soap_passport_sso_handle_response in protocols/msn/soap.c */ ivItem.len = 8; secParam = PK11_ParamFromIV(CIPHER_MECH, &ivItem); if (secParam == NULL) { fprintf(stderr, "PK11_ParamFromIV failed (err %d)\n", PR_GetError()); rc = 0; goto out; } ctx = PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey, secParam); if (ctx == NULL) { fprintf(stderr, "PK11_CreateContextBySymKey failed (err %d)\n", PR_GetError()); rc = 0; goto out; } *res = g_new0(unsigned char, MAX_OUTPUT_LEN); rv = PK11_CipherOp(ctx, *res, &len1, MAX_OUTPUT_LEN, (unsigned char *)input, input_len); if (rv != SECSuccess) { fprintf(stderr, "PK11_CipherOp failed (err %d)\n", PR_GetError()); rc = 0; goto out; } assert(len1 <= MAX_OUTPUT_LEN); rv = PK11_DigestFinal(ctx, *res + len1, &len2, (unsigned int)MAX_OUTPUT_LEN - len1); if (rv != SECSuccess) { fprintf(stderr, "PK11_DigestFinal failed (err %d)\n", PR_GetError()); rc = 0; goto out; } rc = len1 + len2; out: if (ctx) PK11_DestroyContext(ctx, PR_TRUE); if (symKey) PK11_FreeSymKey(symKey); if (secParam) SECITEM_FreeItem(secParam, PR_TRUE); if (slot) PK11_FreeSlot(slot); return rc; }
/* * CreatePk11PinStore */ int CreatePk11PinStore(Pk11PinStore **out, const char *tokenName, const char *pin) { int err = PIN_SUCCESS; Pk11PinStore *store; do { store = (Pk11PinStore*)malloc(sizeof(Pk11PinStore)); if (store == 0) { err = PIN_NOMEMORY; break; } /* Low-level init */ store->key = 0; store->params = 0; store->crypt = 0; /* Use the tokenName to find a PKCS11 slot */ store->slot = PK11_FindSlotByName((char *)tokenName); if (store->slot == 0) { err = PIN_NOSUCHTOKEN; break; } /* Check the password/PIN. This allows access to the token */ { SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin); if (rv == SECSuccess) ; else if (rv == SECWouldBlock) { /* NSS returns a blocking error when the pin is wrong */ err = PIN_INCORRECTPW; break; } else { err = PIN_SYSTEMERROR; break; } } /* Find the mechanism that this token can do */ { const mech_item *tp; store->mech = 0; for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++) { if (PK11_DoesMechanism(store->slot, tp->type)) { store->mech = (mech_item *)tp; break; } } /* Default to a mechanism (probably on the internal token */ if (store->mech == 0) { store->mech = &dflt_mech; } } /* Generate a key and parameters to do the encryption */ #if NSS_VMAJOR >= 3 && (NSS_VMINOR <= 9 || (NSS_VMINOR <= 10 && NSS_VPATCH == 0)) store->key = PK11_KeyGen(store->slot, store->mech->type, 0, 0, 0); #else store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type, NULL, 0, NULL, CKF_ENCRYPT|CKF_DECRYPT, PR_FALSE, NULL); #endif if (store->key == 0) { /* PR_SetError(xxx); */ err = PIN_SYSTEMERROR; break; } store->params = PK11_GenerateNewParam(store->mech->type, store->key); if (store->params == 0) { err = PIN_SYSTEMERROR; break; } /* 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 *)malloc(store->length); if (!store->crypt) { err = PIN_NOMEMORY; break; } } /* Encrypt */ { unsigned char *plain; PK11Context *ctx; SECStatus rv; int outLen; plain = (unsigned char *)malloc(store->length); if (!plain) { err = PIN_NOMEMORY; break; } /* Pad with 0 bytes */ memset(plain, 0, store->length); strcpy((char *)plain, pin); ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT, store->key, store->params); if (!ctx) { err = PIN_SYSTEMERROR; 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 = PIN_SYSTEMERROR; } } while(0); if (err) { DestroyPk11PinStore(store); store = 0; } *out = store; return err; }
/* the content of an encrypted data content info is decrypted. * it is assumed that for encrypted data, that the data has already * been set and is in the "encContent" field of the content info. * * cinfo is the content info to decrypt * * key is the key with which to perform the decryption. if the * algorithm is a password based encryption algorithm, the * key is actually a password which will be processed per * PKCS #5. * * in the event of an error, SECFailure is returned. SECSuccess * indicates a success. */ SECStatus SEC_PKCS7DecryptContents(PRArenaPool *poolp, SEC_PKCS7ContentInfo *cinfo, SECItem *key, void *wincx) { SECAlgorithmID *algid = NULL; SECStatus rv = SECFailure; SECItem *result = NULL, *dest, *src; void *mark; PK11SymKey *eKey = NULL; PK11SlotInfo *slot = NULL; CK_MECHANISM_TYPE cryptoMechType; void *cx; SECItem *c_param = NULL; int bs; if((cinfo == NULL) || (key == NULL)) return SECFailure; if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA) return SECFailure; algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo); if(algid == NULL) return SECFailure; if(poolp == NULL) poolp = cinfo->poolp; mark = PORT_ArenaMark(poolp); src = &cinfo->content.encryptedData->encContentInfo.encContent; dest = &cinfo->content.encryptedData->encContentInfo.plainContent; dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64)); dest->len = (src->len + 64); if(dest->data == NULL) { rv = SECFailure; goto loser; } slot = PK11_GetInternalKeySlot(); if(slot == NULL) { rv = SECFailure; goto loser; } eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); if(eKey == NULL) { rv = SECFailure; goto loser; } cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key); if (cryptoMechType == CKM_INVALID_MECHANISM) { rv = SECFailure; goto loser; } cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, eKey, c_param); if(cx == NULL) { rv = SECFailure; goto loser; } rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), (int)(src->len + 64), src->data, (int)src->len); PK11_DestroyContext((PK11Context *)cx, PR_TRUE); bs = PK11_GetBlockSize(cryptoMechType, c_param); if(bs) { /* check for proper badding in block algorithms. this assumes * RC2 cbc or a DES cbc variant. and the padding is thus defined */ if(((int)dest->data[dest->len-1] <= bs) && ((int)dest->data[dest->len-1] > 0)) { dest->len -= (int)dest->data[dest->len-1]; } else { rv = SECFailure; /* set an error ? */ } } loser: /* let success fall through */ if(result != NULL) SECITEM_ZfreeItem(result, PR_TRUE); if(rv == SECFailure) PORT_ArenaRelease(poolp, mark); else PORT_ArenaUnmark(poolp, mark); if(eKey != NULL) PK11_FreeSymKey(eKey); if(slot != NULL) PK11_FreeSlot(slot); if(c_param != NULL) SECITEM_ZfreeItem(c_param, PR_TRUE); return rv; }
/* the content of an encrypted data content info is encrypted. * it is assumed that for encrypted data, that the data has already * been set and is in the "plainContent" field of the content info. * * cinfo is the content info to encrypt * * key is the key with which to perform the encryption. if the * algorithm is a password based encryption algorithm, the * key is actually a password which will be processed per * PKCS #5. * * in the event of an error, SECFailure is returned. SECSuccess * indicates a success. */ SECStatus SEC_PKCS7EncryptContents(PRArenaPool *poolp, SEC_PKCS7ContentInfo *cinfo, SECItem *key, void *wincx) { SECAlgorithmID *algid = NULL; SECItem * result = NULL; SECItem * src; SECItem * dest; SECItem * blocked_data = NULL; void * mark; void * cx; PK11SymKey * eKey = NULL; PK11SlotInfo * slot = NULL; CK_MECHANISM_TYPE cryptoMechType; int bs; SECStatus rv = SECFailure; SECItem *c_param = NULL; if((cinfo == NULL) || (key == NULL)) return SECFailure; if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA) return SECFailure; algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo); if(algid == NULL) return SECFailure; if(poolp == NULL) poolp = cinfo->poolp; mark = PORT_ArenaMark(poolp); src = &cinfo->content.encryptedData->encContentInfo.plainContent; dest = &cinfo->content.encryptedData->encContentInfo.encContent; dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64)); dest->len = (src->len + 64); if(dest->data == NULL) { rv = SECFailure; goto loser; } slot = PK11_GetInternalKeySlot(); if(slot == NULL) { rv = SECFailure; goto loser; } eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); if(eKey == NULL) { rv = SECFailure; goto loser; } cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key); if (cryptoMechType == CKM_INVALID_MECHANISM) { rv = SECFailure; goto loser; } /* block according to PKCS 8 */ bs = PK11_GetBlockSize(cryptoMechType, c_param); rv = SECSuccess; if(bs) { char pad_char; pad_char = (char)(bs - (src->len % bs)); if(src->len % bs) { rv = SECSuccess; blocked_data = PK11_BlockData(src, bs); if(blocked_data) { PORT_Memset((blocked_data->data + blocked_data->len - (int)pad_char), pad_char, (int)pad_char); } else { rv = SECFailure; goto loser; } } else { blocked_data = SECITEM_DupItem(src); if(blocked_data) { blocked_data->data = (unsigned char*)PORT_Realloc( blocked_data->data, blocked_data->len + bs); if(blocked_data->data) { blocked_data->len += bs; PORT_Memset((blocked_data->data + src->len), (char)bs, bs); } else { rv = SECFailure; goto loser; } } else { rv = SECFailure; goto loser; } } } else { blocked_data = SECITEM_DupItem(src); if(!blocked_data) { rv = SECFailure; goto loser; } } cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, eKey, c_param); if(cx == NULL) { rv = SECFailure; goto loser; } rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), (int)(src->len + 64), blocked_data->data, (int)blocked_data->len); PK11_DestroyContext((PK11Context*)cx, PR_TRUE); loser: /* let success fall through */ if(blocked_data != NULL) SECITEM_ZfreeItem(blocked_data, PR_TRUE); if(result != NULL) SECITEM_ZfreeItem(result, PR_TRUE); if(rv == SECFailure) PORT_ArenaRelease(poolp, mark); else PORT_ArenaUnmark(poolp, mark); if(eKey != NULL) PK11_FreeSymKey(eKey); if(slot != NULL) PK11_FreeSlot(slot); if(c_param != NULL) SECITEM_ZfreeItem(c_param, PR_TRUE); return rv; }
TPS_PUBLIC PRStatus Util::ComputeMAC(PK11SymKey *key, Buffer &x_input, const Buffer &icv, Buffer &output) { PRStatus rv = PR_SUCCESS; PK11Context *context = NULL; // NetkeyICV temp; unsigned char result[8]; int i; SECStatus s; int len; #ifdef USE_DESMAC CK_ULONG macLen = sizeof result; SECItem params = { siBuffer, (unsigned char *)&macLen, sizeof macLen }; #endif static SECItem noParams = { siBuffer, 0, 0 }; static unsigned char macPad[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; BYTE *input = (BYTE *) x_input; int inputLen = x_input.size(); #ifdef USE_DESMAC context = PK11_CreateContextBySymKey(CKM_DES3_MAC_GENERAL, CKA_SIGN, key, ¶ms); if (!context) { rv = PR_FAILURE; goto done; } s = PK11_DigestBegin(context); if (s != SECSuccess) { rv = PR_FAILURE; goto done; } s = PK11_DigestOp(context, icv, 8); if (s != SECSuccess) { rv = PR_FAILURE; goto done; } while(inputLen >= 8) { s = PK11_DigestOp(context, input, 8); if (s != SECSuccess) { rv = PR_FAILURE; goto done; } input += 8; inputLen -= 8; } for (i = 0;i < inputLen;i++) { result[i] = input[i]; } input = macPad; for(;i < 8;i++) { result[i] = *input++; } s = PK11_DigestOp(context, result, sizeof result); if (s != SECSuccess) { rv = PR_FAILURE; goto done; } s = PK11_DigestFinal(context, output, (unsigned int *)&len, sizeof output); if (1 != SECSuccess) { rv = PR_FAILURE; goto done; } #else context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, &noParams); if (!context) { rv = PR_FAILURE; goto done; } memcpy(result, icv, sizeof result); /* Process whole blocks */ while(inputLen >= 8) { for(i = 0;i < 8;i++) { result[i] ^= input[i]; } s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result); if (s != SECSuccess) { rv = PR_FAILURE; goto done; } if (len != sizeof result) /* assert? */ { //PR_SetError(PR_UNKNOWN_ERROR, 0); rv = PR_FAILURE; goto done; } input += 8; inputLen -= 8; } /* * Fold in remaining data (if any) * Set i to number of bytes processed */ for(i = 0;i < inputLen;i++) { result[i] ^= input[i]; } /* * Fill remainder of last block. There * will be at least one byte handled here. */ input = macPad; while(i < 8) { result[i] ^= *input++; i++; } s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result); if (s != SECSuccess) { rv = PR_FAILURE; goto done; } if (len != sizeof result) { //PR_SetError(PR_UNKNOWN_ERROR, 0); rv = PR_FAILURE; goto done; } output.replace(0, result, sizeof result); #endif done: if( context != NULL ) { PK11_Finalize( context ); PK11_DestroyContext( context, PR_TRUE ); context = NULL; } memset(result, 0, sizeof result); return rv; } /* ComputeMAC */
/* encrypt a block (XMLSEC_NSS_AES_BLOCK_SIZE), in and out can overlap */ static void xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out, int enc) { CK_MECHANISM_TYPE cipherMech; SECItem* SecParam = NULL; PK11Context* EncContext = NULL; SECStatus rv; int tmp1_outlen; unsigned int tmp2_outlen; xmlSecAssert(in != NULL); xmlSecAssert(out != NULL); cipherMech = CKM_AES_ECB; SecParam = PK11_ParamFromIV(cipherMech, NULL); if (SecParam == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_ParamFromIV", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } EncContext = PK11_CreateContextBySymKey(cipherMech, enc ? CKA_ENCRYPT : CKA_DECRYPT, aeskey, SecParam); if (EncContext == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_CreateContextBySymKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } tmp1_outlen = tmp2_outlen = 0; rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, XMLSEC_NSS_AES_BLOCK_SIZE, (unsigned char *)in, XMLSEC_NSS_AES_BLOCK_SIZE); if (rv != SECSuccess) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_CipherOp", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } rv = PK11_DigestFinal(EncContext, out+tmp1_outlen, &tmp2_outlen, XMLSEC_NSS_AES_BLOCK_SIZE-tmp1_outlen); if (rv != SECSuccess) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_DigestFinal", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } done: if (SecParam) { SECITEM_FreeItem(SecParam, PR_TRUE); } if (EncContext) { PK11_DestroyContext(EncContext, PR_TRUE); } }
static void do_aes(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc) { u_int8_t iv_bak[AES_CBC_BLOCK_SIZE]; u_int8_t *new_iv = NULL; /* logic will avoid copy to NULL */ u_int8_t *tmp_buf; CK_MECHANISM_TYPE ciphermech; SECItem ivitem; SECItem* secparam = NULL; PK11SymKey* symkey = NULL; PK11Context* enccontext = NULL; SECStatus rv; int outlen; DBG(DBG_CRYPT, DBG_log("NSS do_aes: enter")); ciphermech = CKM_AES_CBC; /*libreswan provides padding*/ memcpy(&symkey, key, key_size); if (symkey == NULL) { loglog(RC_LOG_SERIOUS, "do_aes: NSS derived enc key in NULL\n"); goto out; } ivitem.type = siBuffer; ivitem.data = iv; ivitem.len = AES_CBC_BLOCK_SIZE; secparam = PK11_ParamFromIV(ciphermech, &ivitem); if (secparam == NULL) { loglog(RC_LOG_SERIOUS, "do_aes: Failure to set up PKCS11 param (err %d)\n",PR_GetError()); goto out; } outlen = 0; tmp_buf= PR_Malloc((PRUint32)buf_len); if (!enc){ memcpy(new_iv=iv_bak,(char*) buf + buf_len-AES_CBC_BLOCK_SIZE,AES_CBC_BLOCK_SIZE); } enccontext = PK11_CreateContextBySymKey(ciphermech, enc? CKA_ENCRYPT : CKA_DECRYPT, symkey, secparam); rv = PK11_CipherOp(enccontext, tmp_buf, &outlen, buf_len, buf, buf_len); passert(rv==SECSuccess); PK11_DestroyContext(enccontext, PR_TRUE); memcpy(buf,tmp_buf,buf_len); if(enc){ new_iv = (u_int8_t*) buf + buf_len-AES_CBC_BLOCK_SIZE; } memcpy(iv, new_iv, AES_CBC_BLOCK_SIZE); PR_Free(tmp_buf); out: if (secparam) SECITEM_FreeItem(secparam, PR_TRUE); DBG(DBG_CRYPT, DBG_log("NSS do_aes: exit")); }
static int encrypt_nss( knet_handle_t knet_h, const struct iovec *iov, int iovcnt, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* crypt_context = NULL; SECItem crypt_param; SECItem *nss_sec_param = NULL; int tmp_outlen = 0, tmp1_outlen = 0; unsigned int tmp2_outlen = 0; unsigned char *salt = buf_out; unsigned char *data = buf_out + SALT_SIZE; int err = -1; int i; if (PK11_GenerateRandom (salt, SALT_SIZE) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to generate a random number %d", PR_GetError()); goto out; } crypt_param.type = siBuffer; crypt_param.data = salt; crypt_param.len = SALT_SIZE; nss_sec_param = PK11_ParamFromIV (cipher_to_nss[instance->crypto_cipher_type], &crypt_param); if (nss_sec_param == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to set up PKCS11 param (err %d)", PR_GetError()); goto out; } /* * Create cipher context for encryption */ crypt_context = PK11_CreateContextBySymKey (cipher_to_nss[instance->crypto_cipher_type], CKA_ENCRYPT, instance->nss_sym_key, nss_sec_param); if (!crypt_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d)", (int)cipher_to_nss[instance->crypto_cipher_type], PR_GetError()); goto out; } for (i=0; i<iovcnt; i++) { if (PK11_CipherOp(crypt_context, data, &tmp_outlen, KNET_DATABUFSIZE_CRYPT, (unsigned char *)iov[i].iov_base, iov[i].iov_len) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp failed (encrypt) crypt_type=%d (err %d)", (int)cipher_to_nss[instance->crypto_cipher_type], PR_GetError()); goto out; } tmp1_outlen = tmp1_outlen + tmp_outlen; } if (PK11_DigestFinal(crypt_context, data + tmp1_outlen, &tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal failed (encrypt) crypt_type=%d (err %d)", (int)cipher_to_nss[instance->crypto_cipher_type], PR_GetError()); goto out; } *buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE; err = 0; out: if (crypt_context) { PK11_DestroyContext(crypt_context, PR_TRUE); } if (nss_sec_param) { SECITEM_FreeItem(nss_sec_param, PR_TRUE); } return err; }
/* * SVRCORE_CreatePk11PinStore */ SVRCOREError SVRCORE_CreatePk11PinStore( SVRCOREPk11PinStore **out, const char *tokenName, const char *pin) { SVRCOREError err; SVRCOREPk11PinStore *store; do { err = SVRCORE_Success; store = (SVRCOREPk11PinStore*)malloc(sizeof *store); if (store == 0) { err = SVRCORE_NoMemory_Error; break; } /* Low-level init */ store->slot = 0; store->key = 0; store->params = 0; store->crypt = 0; /* Use the tokenName to find a PKCS11 slot */ store->slot = PK11_FindSlotByName((char *)tokenName); if (store->slot == 0) { err = SVRCORE_NoSuchToken_Error; break; } /* Check the password/PIN. This allows access to the token */ { SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin); if (rv == SECSuccess) ; else if (rv == SECWouldBlock) { err = SVRCORE_IncorrectPassword_Error; break; } else { err = SVRCORE_System_Error; break; } } /* Find the mechanism that this token can do */ { const mech_item *tp; store->mech = 0; for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++) { if (PK11_DoesMechanism(store->slot, tp->type)) { store->mech = tp; break; } } /* Default to a mechanism (probably on the internal token */ if (store->mech == 0) store->mech = &dflt_mech; } /* Generate a key and parameters to do the encryption */ store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type, 0, 0, 0, CKF_ENCRYPT|CKF_DECRYPT, 0, 0); if (store->key == 0) { /* PR_SetError(xxx); */ err = SVRCORE_System_Error; break; } store->params = PK11_GenerateNewParam(store->mech->type, store->key); if (store->params == 0) { err = SVRCORE_System_Error; break; } /* 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 *)malloc(store->length); if (!store->crypt) { err = SVRCORE_NoMemory_Error; break; } } /* Encrypt */ { unsigned char *plain; PK11Context *ctx; SECStatus rv; int outLen; plain = (unsigned char *)malloc(store->length); if (!plain) { err = SVRCORE_NoMemory_Error; break; } /* Pad with 0 bytes */ memset(plain, 0, store->length); strcpy((char *)plain, pin); ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT, store->key, store->params); if (!ctx) { err = SVRCORE_System_Error; 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 = SVRCORE_System_Error; } } while(0); if (err) { SVRCORE_DestroyPk11PinStore(store); store = 0; } *out = store; return err; }
TPS_PUBLIC PRStatus Util::EncryptData(Buffer &kek_key, Buffer &input, Buffer &output) { PRStatus rv = PR_FAILURE; PK11SymKey *master = NULL; PK11SlotInfo *slot = PK11_GetInternalKeySlot(); PK11Context *context = NULL; int i; SECStatus s = SECFailure; int len; static SECItem noParams = { siBuffer, 0, 0 }; #ifdef DES2_WORKAROUND unsigned char masterKeyData[24]; #else unsigned char masterKeyData[16]; #endif SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; unsigned char result[8]; // convert 16-byte to 24-byte triple-DES key memcpy(masterKeyData, (BYTE*)kek_key, 16); #ifdef DES2_WORKAROUND memcpy(masterKeyData+16, (BYTE*)kek_key, 8); #endif master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, CKF_ENCRYPT, PR_FALSE, 0); if( ! master ) { goto done; } context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, &noParams); if (!context) { goto done; } for(i = 0;i < (int)input.size();i += 8) { s = PK11_CipherOp(context, result, &len, 8, (unsigned char *)(((BYTE*)input)+i), 8); if (s != SECSuccess) { goto done; } output.replace(i, result, 8); } rv = PR_SUCCESS; done: memset(masterKeyData, 0, sizeof masterKeyData); if( context != NULL ) { PK11_DestroyContext( context, PR_TRUE ); context = NULL; } if( slot != NULL ) { PK11_FreeSlot( slot ); slot = NULL; } if( master != NULL ) { PK11_FreeSymKey( master ); master = NULL; } return rv; }
void do_3des_nss(u_int8_t *buf, size_t buf_len, PK11SymKey *symkey, u_int8_t *iv, bool enc) { u_int8_t *tmp_buf; u_int8_t *new_iv; CK_MECHANISM_TYPE ciphermech; SECItem ivitem; SECItem *secparam; PK11Context *enccontext = NULL; SECStatus rv; int outlen; DBG(DBG_CRYPT, DBG_log("NSS: do_3des init start")); ciphermech = CKM_DES3_CBC; /* libreswan provides padding */ if (symkey == NULL) { loglog(RC_LOG_SERIOUS, "do_3des: NSS derived enc key is NULL"); abort(); } ivitem.type = siBuffer; ivitem.data = iv; ivitem.len = DES_CBC_BLOCK_SIZE; secparam = PK11_ParamFromIV(ciphermech, &ivitem); if (secparam == NULL) { loglog(RC_LOG_SERIOUS, "do_3des: Failure to set up PKCS11 param (err %d)", PR_GetError()); abort(); } outlen = 0; tmp_buf = PR_Malloc((PRUint32)buf_len); new_iv = (u_int8_t*)PR_Malloc((PRUint32)DES_CBC_BLOCK_SIZE); if (!enc) memcpy(new_iv, (char*) buf + buf_len - DES_CBC_BLOCK_SIZE, DES_CBC_BLOCK_SIZE); enccontext = PK11_CreateContextBySymKey(ciphermech, enc ? CKA_ENCRYPT : CKA_DECRYPT, symkey, secparam); if (enccontext == NULL) { loglog(RC_LOG_SERIOUS, "do_3des: PKCS11 context creation failure (err %d)", PR_GetError()); abort(); } rv = PK11_CipherOp(enccontext, tmp_buf, &outlen, buf_len, buf, buf_len); if (rv != SECSuccess) { loglog(RC_LOG_SERIOUS, "do_3des: PKCS11 operation failure (err %d)", PR_GetError()); abort(); } if (enc) memcpy(new_iv, (char*) tmp_buf + buf_len - DES_CBC_BLOCK_SIZE, DES_CBC_BLOCK_SIZE); memcpy(buf, tmp_buf, buf_len); memcpy(iv, new_iv, DES_CBC_BLOCK_SIZE); PK11_DestroyContext(enccontext, PR_TRUE); PR_Free(tmp_buf); PR_Free(new_iv); if (secparam != NULL) SECITEM_FreeItem(secparam, PR_TRUE); DBG(DBG_CRYPT, DBG_log("NSS: do_3des init end")); }
TPS_PUBLIC PK11SymKey *Util::DeriveKey(const Buffer& permKey, const Buffer& hostChallenge, const Buffer& cardChallenge) { PK11SymKey *key = NULL, *master = NULL; PK11SlotInfo *slot = PK11_GetInternalKeySlot(); PK11Context *context = NULL; unsigned char derivationData[16]; #ifdef DES2_WORKAROUND unsigned char keyData[24]; #else unsigned char keyData[16]; #endif int i; SECStatus s; int len; SECItem keyItem = { siBuffer, keyData, sizeof keyData }; static SECItem noParams = { siBuffer, 0, 0 }; BYTE masterKeyData[24]; SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; // convert 16-byte to 24-byte triple-DES key memcpy(masterKeyData, permKey, 16); memcpy(masterKeyData+16, permKey, 8); master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, CKF_ENCRYPT, PR_FALSE, 0); if( ! master ) goto done; for(i = 0;i < 4;i++) { derivationData[i] = cardChallenge[i+4]; derivationData[i+4] = hostChallenge[i]; derivationData[i+8] = cardChallenge[i]; derivationData[i+12] = hostChallenge[i+4]; } context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, &noParams); if (!context) goto done; /* Part 1 */ s = PK11_CipherOp(context, &keyData[0], &len, 8, &derivationData[0], 8); if (s != SECSuccess) goto done; /* Part 2 */ s = PK11_CipherOp(context, &keyData[8], &len, 8, &derivationData[8], 8); if (s != SECSuccess) goto done; #ifdef DES2_WORKAROUND /* Part 3 */ for(i = 0;i < 8;i++) { keyData[i+16] = keyData[i]; } #endif key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated, CKA_ENCRYPT, &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0); done: memset(keyData, 0, sizeof keyData); if( context != NULL ) { PK11_DestroyContext( context, PR_TRUE ); context = NULL; } if( slot != NULL ) { PK11_FreeSlot( slot ); slot = NULL; } if( master != NULL ) { PK11_FreeSymKey( master ); master = NULL; } return key; }
char * crypto_encrypt (const char *cipher, const guint8 *data, gsize data_len, const char *iv, gsize iv_len, const char *key, gsize key_len, gsize *out_len, GError **error) { SECStatus ret; CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; PK11SlotInfo *slot = NULL; SECItem key_item = { .data = (unsigned char *) key, .len = key_len }; SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len }; PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; unsigned char *output, *padded_buf; gsize output_len; int encrypted_len = 0, i; gboolean success = FALSE; gsize padded_buf_len, pad_len; if (!crypto_init (error)) return NULL; if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) cipher_mech = CKM_DES3_CBC_PAD; else if (!strcmp (cipher, CIPHER_AES_CBC)) cipher_mech = CKM_AES_CBC_PAD; else { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Private key cipher '%s' was unknown."), cipher); return NULL; } /* If data->len % ivlen == 0, then we add another complete block * onto the end so that the decrypter knows there's padding. */ pad_len = iv_len - (data_len % iv_len); output_len = padded_buf_len = data_len + pad_len; padded_buf = g_malloc0 (padded_buf_len); memcpy (padded_buf, data, data_len); for (i = 0; i < pad_len; i++) padded_buf[data_len + i] = (guint8) (pad_len & 0xFF); output = g_malloc0 (output_len); slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the encryption cipher slot.")); goto out; } sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if (!sym_key) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set symmetric key for encryption.")); goto out; } sec_param = PK11_ParamFromIV (cipher_mech, &iv_item); if (!sec_param) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set IV for encryption.")); goto out; } ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param); if (!ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to initialize the encryption context.")); goto out; } ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len); if (ret != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to encrypt: %d."), PORT_GetError ()); goto out; } if (encrypted_len != output_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Unexpected amount of data after encrypting.")); goto out; } *out_len = encrypted_len; success = TRUE; out: if (ctx) PK11_DestroyContext (ctx, PR_TRUE); if (sym_key) PK11_FreeSymKey (sym_key); if (sec_param) SECITEM_FreeItem (sec_param, PR_TRUE); if (slot) PK11_FreeSlot (slot); memset (padded_buf, 0, padded_buf_len); g_free (padded_buf); if (!success) { memset (output, 0, output_len); g_free (output); output = NULL; } return (char *) output; } NMCryptoFileFormat crypto_verify_cert (const unsigned char *data, gsize len, GError **error) { CERTCertificate *cert; if (!crypto_init (error)) return NM_CRYPTO_FILE_FORMAT_UNKNOWN; /* Try DER/PEM first */ cert = CERT_DecodeCertFromPackage ((char *) data, len); if (!cert) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode certificate: %d"), PORT_GetError()); return NM_CRYPTO_FILE_FORMAT_UNKNOWN; } CERT_DestroyCertificate (cert); return NM_CRYPTO_FILE_FORMAT_X509; } gboolean crypto_verify_pkcs12 (const guint8 *data, gsize data_len, const char *password, GError **error) { SEC_PKCS12DecoderContext *p12ctx = NULL; SECItem pw = { 0 }; PK11SlotInfo *slot = NULL; SECStatus s; gunichar2 *ucs2_password; glong ucs2_chars = 0; #ifndef WORDS_BIGENDIAN guint16 *p; #endif /* WORDS_BIGENDIAN */ if (error) g_return_val_if_fail (*error == NULL, FALSE); if (!crypto_init (error)) return FALSE; /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do * any conversions for us. */ if (password && *password) { if (!g_utf8_validate (password, -1, NULL)) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_PASSWORD, _("Password must be UTF-8")); return FALSE; } ucs2_password = g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL); /* Can't fail if g_utf8_validate() succeeded */ g_return_val_if_fail (ucs2_password != NULL && ucs2_chars != 0, FALSE); ucs2_chars *= 2; /* convert # UCS2 characters -> bytes */ pw.data = PORT_ZAlloc(ucs2_chars + 2); memcpy (pw.data, ucs2_password, ucs2_chars); pw.len = ucs2_chars + 2; /* include terminating NULL */ memset (ucs2_password, 0, ucs2_chars); g_free (ucs2_password); #ifndef WORDS_BIGENDIAN for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++) *p = GUINT16_SWAP_LE_BE (*p); #endif /* WORDS_BIGENDIAN */ } else { /* NULL password */ pw.data = NULL; pw.len = 0; } slot = PK11_GetInternalKeySlot(); p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); if (!p12ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize PKCS#12 decoder: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderUpdate (p12ctx, (guint8 *)data, data_len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#12 file: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderVerify (p12ctx); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Couldn't verify PKCS#12 file: %d"), PORT_GetError()); goto error; } SEC_PKCS12DecoderFinish (p12ctx); SECITEM_ZfreeItem (&pw, PR_FALSE); return TRUE; error: if (p12ctx) SEC_PKCS12DecoderFinish (p12ctx); if (slot) PK11_FreeSlot(slot); SECITEM_ZfreeItem (&pw, PR_FALSE); return FALSE; }
static void ike_alg_nss_cbc(const struct encrypt_desc *alg, u_int8_t *in_buf, size_t in_buf_len, PK11SymKey *symkey, u_int8_t *iv, bool enc) { DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - enter", alg->common.name)); if (symkey == NULL) { PASSERT_FAIL("%s - NSS derived enc key in NULL", alg->common.name); } SECItem ivitem; ivitem.type = siBuffer; ivitem.data = iv; ivitem.len = alg->enc_blocksize; SECItem *secparam = PK11_ParamFromIV(alg->common.nss_mechanism, &ivitem); if (secparam == NULL) { PASSERT_FAIL("%s - Failure to set up PKCS11 param (err %d)", alg->common.name, PR_GetError()); } PK11Context *enccontext; enccontext = PK11_CreateContextBySymKey(alg->common.nss_mechanism, enc ? CKA_ENCRYPT : CKA_DECRYPT, symkey, secparam); if (enccontext == NULL) { PASSERT_FAIL("%s - PKCS11 context creation failure (err %d)", alg->common.name, PR_GetError()); } /* Output buffer for transformed data. */ u_int8_t *out_buf = PR_Malloc((PRUint32)in_buf_len); int out_buf_len = 0; SECStatus rv = PK11_CipherOp(enccontext, out_buf, &out_buf_len, in_buf_len, in_buf, in_buf_len); if (rv != SECSuccess) { PASSERT_FAIL("%s - PKCS11 operation failure (err %d)", alg->common.name, PR_GetError()); } PK11_DestroyContext(enccontext, PR_TRUE); /* * Update the IV ready for the next call to this function. */ u_int8_t *new_iv; if (enc) { /* * The IV for the next encryption call is the last * block of encrypted output data. */ new_iv = out_buf + out_buf_len - alg->enc_blocksize; } else { /* * The IV for the next decryption call is the last * block of the encrypted input data. */ new_iv = in_buf + in_buf_len - alg->enc_blocksize; } memcpy(iv, new_iv, alg->enc_blocksize); /* * Finally, copy the transformed data back to the buffer. Do * this after extracting the IV. */ memcpy(in_buf, out_buf, in_buf_len); PR_Free(out_buf); if (secparam != NULL) SECITEM_FreeItem(secparam, PR_TRUE); DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - exit", alg->common.name)); }
char * crypto_decrypt (const char *cipher, int key_type, const guint8 *data, gsize data_len, const char *iv, const gsize iv_len, const char *key, const gsize key_len, gsize *out_len, GError **error) { char *output = NULL; int decrypted_len = 0; CK_MECHANISM_TYPE cipher_mech; PK11SlotInfo *slot = NULL; SECItem key_item; PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; SECStatus s; gboolean success = FALSE; unsigned int pad_len = 0, extra = 0; guint32 i, real_iv_len = 0; if (!crypto_init (error)) return NULL; if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) { cipher_mech = CKM_DES3_CBC_PAD; real_iv_len = 8; } else if (!strcmp (cipher, CIPHER_DES_CBC)) { cipher_mech = CKM_DES_CBC_PAD; real_iv_len = 8; } else if (!strcmp (cipher, CIPHER_AES_CBC)) { cipher_mech = CKM_AES_CBC_PAD; real_iv_len = 16; } else { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Private key cipher '%s' was unknown."), cipher); return NULL; } if (iv_len < real_iv_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Invalid IV length (must be at least %d)."), real_iv_len); return NULL; } output = g_malloc0 (data_len); slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the decryption cipher slot.")); goto out; } key_item.data = (unsigned char *) key; key_item.len = key_len; sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL); if (!sym_key) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to set symmetric key for decryption.")); goto out; } key_item.data = (unsigned char *) iv; key_item.len = real_iv_len; sec_param = PK11_ParamFromIV (cipher_mech, &key_item); if (!sec_param) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to set IV for decryption.")); goto out; } ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_DECRYPT, sym_key, sec_param); if (!ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to initialize the decryption context.")); goto out; } s = PK11_CipherOp (ctx, (unsigned char *) output, &decrypted_len, data_len, data, data_len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: %d."), PORT_GetError ()); goto out; } if (decrypted_len > data_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: decrypted data too large.")); goto out; } s = PK11_DigestFinal (ctx, (unsigned char *) (output + decrypted_len), &extra, data_len - decrypted_len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to finalize decryption of the private key: %d."), PORT_GetError ()); goto out; } decrypted_len += extra; pad_len = data_len - decrypted_len; /* Check if the padding at the end of the decrypted data is valid */ if (pad_len == 0 || pad_len > real_iv_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: unexpected padding length.")); goto out; } /* Validate tail padding; last byte is the padding size, and all pad bytes * should contain the padding size. */ for (i = pad_len; i > 0; i--) { if (output[data_len - i] != pad_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key.")); goto out; } } *out_len = decrypted_len; success = TRUE; out: if (ctx) PK11_DestroyContext (ctx, PR_TRUE); if (sym_key) PK11_FreeSymKey (sym_key); if (sec_param) SECITEM_FreeItem (sec_param, PR_TRUE); if (slot) PK11_FreeSlot (slot); if (!success) { if (output) { /* Don't expose key material */ memset (output, 0, data_len); g_free (output); output = NULL; } } return output; }
static gboolean purple_aes_cipher_nss_crypt(const guchar *input, guchar *output, size_t len, guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, CK_ATTRIBUTE_TYPE operation) { PurpleAESCipherNSSContext context; CK_MECHANISM_TYPE cipher_mech = CKM_AES_CBC; SECItem key_item, iv_item; SECStatus ret; int outlen = 0; unsigned int outlen_tmp = 0; memset(&context, 0, sizeof(PurpleAESCipherNSSContext)); if (NSS_NoDB_Init(NULL) != SECSuccess) { purple_debug_error("cipher-aes", "NSS_NoDB_Init failed: %d\n", PR_GetError()); return FALSE; } context.slot = PK11_GetBestSlot(cipher_mech, NULL); if (context.slot == NULL) { purple_debug_error("cipher-aes", "PK11_GetBestSlot failed: %d\n", PR_GetError()); return FALSE; } key_item.type = siBuffer; key_item.data = key; key_item.len = key_size; context.sym_key = PK11_ImportSymKey(context.slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if (context.sym_key == NULL) { purple_debug_error("cipher-aes", "PK11_ImportSymKey failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } iv_item.type = siBuffer; iv_item.data = iv; iv_item.len = PURPLE_AES_BLOCK_SIZE; context.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); if (context.sec_param == NULL) { purple_debug_error("cipher-aes", "PK11_ParamFromIV failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } context.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation, context.sym_key, context.sec_param); if (context.enc_context == NULL) { purple_debug_error("cipher-aes", "PK11_CreateContextBySymKey failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } ret = PK11_CipherOp(context.enc_context, output, &outlen, len, (guchar *)input, len); if (ret != SECSuccess) { purple_debug_error("cipher-aes", "PK11_CipherOp failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } ret = PK11_DigestFinal(context.enc_context, output + outlen, &outlen_tmp, len - outlen); if (ret != SECSuccess) { purple_debug_error("cipher-aes", "PK11_DigestFinal failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } purple_aes_cipher_nss_cleanup(&context); outlen += outlen_tmp; if (outlen != (int)len) { purple_debug_error("cipher-aes", "resulting length doesn't match: %d (expected: %lu)\n", outlen, len); return FALSE; } return TRUE; }
static int xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize, const xmlSecByte *in, xmlSecSize inSize, xmlSecByte *out, xmlSecSize outSize, int enc) { CK_MECHANISM_TYPE cipherMech; PK11SlotInfo* slot = NULL; PK11SymKey* aeskey = NULL; SECItem* SecParam = NULL; PK11Context* EncContext = NULL; SECItem keyItem; SECStatus rv; int result_len = -1; int tmp1_outlen; unsigned int tmp2_outlen; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(keySize > 0, -1); xmlSecAssert2(in != NULL, -1); xmlSecAssert2(inSize > 0, -1); xmlSecAssert2(out != NULL, -1); xmlSecAssert2(outSize >= inSize + 8, -1); cipherMech = CKM_NETSCAPE_AES_KEY_WRAP; slot = PK11_GetBestSlot(cipherMech, NULL); if (slot == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_GetBestSlot", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } keyItem.data = (unsigned char *)key; keyItem.len = keySize; aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL); if (aeskey == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_ImportSymKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } SecParam = PK11_ParamFromIV(cipherMech, NULL); if (SecParam == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_ParamFromIV", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } EncContext = PK11_CreateContextBySymKey(cipherMech, enc ? CKA_ENCRYPT : CKA_DECRYPT, aeskey, SecParam); if (EncContext == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_CreateContextBySymKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } tmp1_outlen = tmp2_outlen = 0; rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, outSize, (unsigned char *)in, inSize); if (rv != SECSuccess) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_CipherOp", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } rv = PK11_DigestFinal(EncContext, out+tmp1_outlen, &tmp2_outlen, outSize-tmp1_outlen); if (rv != SECSuccess) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_DigestFinal", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } result_len = tmp1_outlen + tmp2_outlen; done: if (slot) { PK11_FreeSlot(slot); } if (aeskey) { PK11_FreeSymKey(aeskey); } if (SecParam) { SECITEM_FreeItem(SecParam, PR_TRUE); } if (EncContext) { PK11_DestroyContext(EncContext, PR_TRUE); } return(result_len); }
TPS_PUBLIC PRStatus Util::ComputeKeyCheck(const Buffer& newKey, Buffer& output) { PK11SymKey *key = NULL; PRStatus status = PR_FAILURE ; PK11SlotInfo *slot = PK11_GetInternalKeySlot(); PK11Context *context = NULL; SECStatus s = SECFailure; int len; static SECItem noParams = { siBuffer, 0, 0 }; #ifdef DES2_WORKAROUND unsigned char keyData[24]; #else unsigned char keyData[16]; #endif SECItem keyItem = {siBuffer, keyData, sizeof(keyData) }; unsigned char value[8]; // convert 16-byte to 24-byte triple-DES key memcpy(keyData, newKey, 16); #ifdef DES2_WORKAROUND memcpy(keyData+16, newKey, 8); #endif memset(value, 0, sizeof value); key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated, CKA_ENCRYPT, &keyItem, CKF_ENCRYPT, PR_FALSE, 0); if( ! key ) { goto done; } context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, &noParams); if (!context) { goto done; } s = PK11_CipherOp(context, &value[0], &len, 8, &value[0], 8); if (s != SECSuccess) { goto done; } output.resize(3); output.replace(0, value, 3); status = PR_SUCCESS; done: memset(keyData, 0, sizeof keyData); if( context != NULL ) { PK11_DestroyContext( context, PR_TRUE ); context = NULL; } if( slot != NULL ) { PK11_FreeSlot( slot ); slot = NULL; } if( key != NULL ) { PK11_FreeSymKey( key ); key = NULL; } return status; }