Hi all,In my epic quest to make NSS encrypt a string, I have managed to successfully create a key from a passphrase, and I have successfully managed to call PK11_CreateContextBySymKey to create an encryption context.
The next error happens at the PK11_CipherOp stage, and resolves to SEC_ERROR_IO, which I understand means "an error has occurred". Unfortunately it gives no more details than that.
Can anyone confirm from the trace below whether any of the parameters used are incorrect, or whether I have missed a step in this process?
The lack of NSS documentation means that I am coding completely in the dark. Much of this code is based on existing code out there (most specifically the weave example and xml-security), and as neither of these are documented either, I am blindly following their recipes, and am still getting nowhere.
In this particular example, I started with SEC_OID_AES_128_ECB, used PK11_AlgtagToMechanism and then PK11_GetPadMechanism to get a cipherMech of 4225 (CKM_AES_ECB).
I then used PK11_CreatePBEV2AlgorithmID to generate a key based on a pbeAlgTag of SEC_OID_AES_128_ECB, a cipherAlgTag based on SEC_OID_AES_128_ECB, and a prfAlgTag SEC_OID_HMAC_SHA1, and this succeeded.
To initialise the encryption I used PK11_GenerateNewParam to create the secParam (as NULL causes failure with no error code), followed by PK11_CreateContextBySymKey using the key and CKM_AES_ECB cipherMech, and this succeeds.
PK11_CipherOp then runs, but fails with SEC_ERROR_IO. Can anyone see anything wrong with the process so far? Here is the details gdb trace of the code flow:Breakpoint 3, crypto_passphrase (p=0x809018, f=0x8090e8, pass=0x116d8 "secret", passLen=6, salt=0x116e0 "salt", saltLen=4, type=KEY_AES_128, mode=MODE_ECB, doPad=1, iterations=4096, k=0xbfffefd4) at crypto/apr_crypto_nss.c:248
248 apr_status_t rv = APR_SUCCESS; (gdb) next 253 void *wincx = NULL; // what is wincx? (gdb) 254 apr_crypto_key_t *key = *k; (gdb) 256 if (!key) { (gdb) 257 *k = key = apr_pcalloc(p, sizeof(apr_crypto_key_t)); (gdb) 259 if (!key) { (gdb) 264 switch (type) { (gdb) 277 if (MODE_CBC == mode) { (gdb) 281 key->cipherOid = SEC_OID_AES_128_ECB; (gdb) 306 key->cipherMech = PK11_AlgtagToMechanism(key->cipherOid); (gdb) 307 if (doPad) { (gdb) 308 key->cipherMech = PK11_GetPadMechanism(key->cipherMech); (gdb) 310 if (key->cipherMech == CKM_INVALID_MECHANISM) { (gdb) 315 passItem.data = (unsigned char*)pass; (gdb) 316 passItem.len = passLen; (gdb) 317 saltItem.data = (unsigned char*)salt; (gdb) 318 saltItem.len = saltLen; (gdb)322 algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid, SEC_OID_HMAC_SHA1, 0, iterations, &saltItem);
(gdb) print key->cipherOid $1 = SEC_OID_AES_128_ECB (gdb) print key->cipherMech $2 = 4225 (gdb) print iterations $3 = 4096 (gdb) next 324 if (algid) { (gdb) 326 slot = PK11_GetBestSlot(key->cipherMech, wincx); (gdb) 327 if (slot) { (gdb)328 key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE, wincx);
(gdb) 329 PK11_FreeSlot(slot); (gdb) 331 SECOID_DestroyAlgorithmID(algid, PR_TRUE); (gdb) 335 if (!key->symKey) { (gdb) 344 return rv; (gdb) print key->symKey $4 = (PK11SymKey *) 0x10cd40 (gdb) print *key->symKey $5 = <incomplete type> (gdb) cont Continuing. -Breakpoint 2, crypto_block_encrypt_init (p=0x809018, f=0x8090e8, key=0x809118, iv=0xbffff078, ctx=0xbfffefbc, ivSize=0xbffff07c) at crypto/apr_crypto_nss.c:376
376 apr_crypto_block_t *block = *ctx; (gdb) next 377 if (!block) { (gdb) 378 *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t)); (gdb) 380 if (!block) { (gdb) 383 block->factory = f; (gdb) 384 block->pool = p; (gdb) 386 apr_pool_cleanup_register(p, block, (gdb) 390 usedIvSize = PK11_GetIVLength(key->cipherMech); (gdb) 391 if (usedIvSize) { (gdb) 414 secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey); (gdb) print usedIvSize $6 = 0 (gdb) next 417 block->blockSize = PK11_GetBlockSize(key->cipherMech, secParam); (gdb)418 block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT, key->symKey, secParam);
(gdb) 421 perr = PORT_GetError(); (gdb) print block->blockSize $7 = 16 (gdb) print block->ctx $8 = (PK11Context *) 0x10ceb0 (gdb) print key->cipherMech $9 = 4225 (gdb) next 422 if (perr || !block->ctx) { (gdb) 428 *ivSize = usedIvSize; (gdb) 429 return APR_SUCCESS; (gdb) cont Continuing. -Breakpoint 4, apr_crypto_block_encrypt (driver=0x1e074, ctx=0x809128, out=0xbffff068, outlen=0xbffff06c, in=0x11d34 "plain text string that is a very long string", inlen=45) at crypto/apr_crypto.c:300
300 return driver->block_encrypt(ctx, out, outlen, in, inlen); (gdb) stepBreakpoint 5, crypto_block_encrypt (block=0x809128, out=0xbffff068, outlen=0xbffff06c, in=0x11d34 "plain text string that is a very long string", inlen=45) at crypto/apr_crypto_nss.c:459
459 int outl = (int) *outlen; (gdb) next 460 if (!out) { (gdb) 464 if (!*out) { (gdb) 465 buffer = apr_palloc(block->pool, inlen + block->blockSize); (gdb) 466 if (!buffer) { (gdb) 469 *out = buffer; (gdb)472 SECStatus s = PK11_CipherOp(block->ctx, *out, &outl, outl, (unsigned char*)in, inlen);
(gdb) 474 if (s != SECSuccess) { (gdb) 475 PRErrorCode perr = PORT_GetError(); (gdb) 476 if (perr) { (gdb) 477 block->factory->result->rc = perr; (gdb) 478 block->factory->result->msg = PR_ErrorToName(perr); (gdb) 480 return APR_ECRYPT; (gdb) print s $10 = SECFailure (gdb) print block->ctx $11 = (PK11Context *) 0x10ceb0 (gdb) print perr $12 = -8192 Regards, Graham --
smime.p7s
Description: S/MIME Cryptographic Signature
_______________________________________________ dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto