From 1509f1d1cb0950725ba488ec110b20409520b752 Mon Sep 17 00:00:00 2001 From: Anant Narayanan Date: Tue, 21 Jul 2009 11:18:29 -0700 Subject: [PATCH] Crypto changes --HG-- extra : rebase_source : 0a953a43c01b95e7c467ec4ca7feeb0aaa00f5e1 --- services/crypto/IWeaveCrypto.idl | 41 ++++ services/crypto/WeaveCrypto.cpp | 191 ++++++++++++++++++ services/crypto/components/IWeaveCrypto.xpt | Bin 529 -> 601 bytes .../Darwin/components/WeaveCrypto.dylib | Bin 65776 -> 65944 bytes .../sync/tests/unit/test_crypto_rewrap.js | 35 ++++ .../sync/tests/unit/test_crypto_verify.js | 23 +++ 6 files changed, 290 insertions(+) create mode 100644 services/sync/tests/unit/test_crypto_rewrap.js create mode 100644 services/sync/tests/unit/test_crypto_verify.js diff --git a/services/crypto/IWeaveCrypto.idl b/services/crypto/IWeaveCrypto.idl index 611f4011d67..36ed444bf2e 100644 --- a/services/crypto/IWeaveCrypto.idl +++ b/services/crypto/IWeaveCrypto.idl @@ -179,5 +179,46 @@ interface IWeaveCrypto : nsISupports in ACString aPassphrase, in ACString aSalt, in ACString aIV); + + /** + * Rewrap a private key with a new user passphrase. + * + * @param aWrappedPrivateKey + * The base64 encoded string holding an encrypted private key. + * @param aPassphrase + * The passphrase to decrypt the private key. + * @param aSalt + * The salt for the passphrase. + * @param aIV + * The random IV used when unwrapping the private key. + * @param aNewPassphrase + * The new passphrase to wrap the private key with. + * @returns The (re)wrapped private key, base64 encoded + * + */ + ACString rewrapPrivateKey(in ACString aWrappedPrivateKey, + in ACString aPassphrase, + in ACString aSalt, + in ACString aIV, + in ACString aNewPassphrase); + + /** + * Verify a user's passphrase against a private key. + * + * @param aWrappedPrivateKey + * The base64 encoded string holding an encrypted private key. + * @param aPassphrase + * The passphrase to decrypt the private key. + * @param aSalt + * The salt for the passphrase. + * @param aIV + * The random IV used when unwrapping the private key. + * @returns Boolean true if the passphrase decrypted the key correctly. + * + */ + boolean verifyPassphrase(in ACString aWrappedPrivateKey, + in ACString aPassphrase, + in ACString aSalt, + in ACString aIV); }; diff --git a/services/crypto/WeaveCrypto.cpp b/services/crypto/WeaveCrypto.cpp index 84714c8b02c..4aa39bea548 100644 --- a/services/crypto/WeaveCrypto.cpp +++ b/services/crypto/WeaveCrypto.cpp @@ -1005,3 +1005,194 @@ unwrap_done: return rv; } + +/* + * RewrapPrivateKey + */ +NS_IMETHODIMP +WeaveCrypto::RewrapPrivateKey(const nsACString& aWrappedPrivateKey, + const nsACString& aPassphrase, + const nsACString& aSalt, + const nsACString& aIV, + const nsACString& aNewPassphrase, + nsACString& aPrivateKey) +{ + nsresult rv = NS_OK; + PK11SlotInfo *slot = nsnull; + PK11SymKey *pbeKey = nsnull; + SECKEYPrivateKey *privKey = nsnull; + SECItem *ivParam = nsnull; + SECItem *keyID = nsnull; + + CK_ATTRIBUTE_TYPE privKeyUsage[] = { CKA_UNWRAP }; + PRUint32 privKeyUsageLength = sizeof(privKeyUsage) / sizeof(CK_ATTRIBUTE_TYPE); + + // Step 1. Get rid of the base64 encoding on the inputs. + char privateKeyBuffer[STACK_BUFFER_SIZE]; + PRUint32 privateKeyBufferSize = sizeof(privateKeyBuffer); + rv = DecodeBase64(aWrappedPrivateKey, privateKeyBuffer, &privateKeyBufferSize); + NS_ENSURE_SUCCESS(rv, rv); + SECItem wrappedPrivKey = {siBuffer, (unsigned char *)privateKeyBuffer, privateKeyBufferSize}; + + + // Step 2. Convert the passphrase to a symmetric key and get the IV in the proper form. + rv = DeriveKeyFromPassphrase(aPassphrase, aSalt, &pbeKey); + NS_ENSURE_SUCCESS(rv, rv); + + char ivData[STACK_BUFFER_SIZE]; + PRUint32 ivDataSize = sizeof(ivData); + rv = DecodeBase64(aIV, ivData, &ivDataSize); + NS_ENSURE_SUCCESS(rv, rv); + SECItem ivItem = {siBuffer, (unsigned char*)ivData, ivDataSize}; + + // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD + CK_MECHANISM_TYPE wrapMech = PK11_AlgtagToMechanism(mAlgorithm); + wrapMech = PK11_GetPadMechanism(wrapMech); + if (wrapMech == CKM_INVALID_MECHANISM) { + NS_WARNING("Unknown key mechanism"); + rv = NS_ERROR_FAILURE; + goto rewrap_done; + } + + ivParam = PK11_ParamFromIV(wrapMech, &ivItem); + if (!ivParam) { + NS_WARNING("Couldn't create IV param"); + rv = NS_ERROR_FAILURE; + goto rewrap_done; + } + + // Step 3. Unwrap the private key with the key from the passphrase. + slot = PK11_GetInternalSlot(); + if (!slot) { + NS_WARNING("Can't get internal PK11 slot"); + rv = NS_ERROR_FAILURE; + goto rewrap_done; + } + + keyID = &ivItem; + privKey = PK11_UnwrapPrivKey(slot, + pbeKey, wrapMech, ivParam, &wrappedPrivKey, + nsnull, + keyID, + PR_FALSE, + PR_TRUE, + CKK_RSA, + privKeyUsage, privKeyUsageLength, + nsnull); + if (!privKey) { + NS_WARNING("PK11_UnwrapPrivKey failed"); + rv = NS_ERROR_FAILURE; + goto rewrap_done; + } + + // Step 4. Rewrap the private key with the new passphrase. + rv = WrapPrivateKey(privKey, aNewPassphrase, aSalt, aIV, aPrivateKey); + if (NS_FAILED(rv)) { + NS_WARNING("RewrapPrivateKey failed"); + rv = NS_ERROR_FAILURE; + goto rewrap_done; + } + +rewrap_done: + if (privKey) + SECKEY_DestroyPrivateKey(privKey); + if (pbeKey) + PK11_FreeSymKey(pbeKey); + if (slot) + PK11_FreeSlot(slot); + if (ivParam) + SECITEM_FreeItem(ivParam, PR_TRUE); + + return rv; +} + +/* + * VerifyPassphrase + */ +NS_IMETHODIMP +WeaveCrypto::VerifyPassphrase(const nsACString& aWrappedPrivateKey, + const nsACString& aPassphrase, + const nsACString& aSalt, + const nsACString& aIV, + PRBool *result) +{ + *result = PR_FALSE; + nsresult rv = NS_OK; + PK11SlotInfo *slot = nsnull; + PK11SymKey *pbeKey = nsnull; + SECKEYPrivateKey *privKey = nsnull; + SECItem *ivParam = nsnull; + SECItem *keyID = nsnull; + + CK_ATTRIBUTE_TYPE privKeyUsage[] = { CKA_UNWRAP }; + PRUint32 privKeyUsageLength = sizeof(privKeyUsage) / sizeof(CK_ATTRIBUTE_TYPE); + + // Step 1. Get rid of the base64 encoding on the input. + char privateKeyBuffer[STACK_BUFFER_SIZE]; + PRUint32 privateKeyBufferSize = sizeof(privateKeyBuffer); + rv = DecodeBase64(aWrappedPrivateKey, privateKeyBuffer, &privateKeyBufferSize); + NS_ENSURE_SUCCESS(rv, rv); + SECItem wrappedPrivKey = {siBuffer, (unsigned char *)privateKeyBuffer, privateKeyBufferSize}; + + // Step 2. Convert the passphrase to a symmetric key and get the IV in the proper form. + rv = DeriveKeyFromPassphrase(aPassphrase, aSalt, &pbeKey); + NS_ENSURE_SUCCESS(rv, rv); + + char ivData[STACK_BUFFER_SIZE]; + PRUint32 ivDataSize = sizeof(ivData); + rv = DecodeBase64(aIV, ivData, &ivDataSize); + NS_ENSURE_SUCCESS(rv, rv); + SECItem ivItem = {siBuffer, (unsigned char*)ivData, ivDataSize}; + + // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD + CK_MECHANISM_TYPE wrapMech = PK11_AlgtagToMechanism(mAlgorithm); + wrapMech = PK11_GetPadMechanism(wrapMech); + if (wrapMech == CKM_INVALID_MECHANISM) { + NS_WARNING("Unknown key mechanism"); + rv = NS_ERROR_FAILURE; + goto verify_done; + } + + ivParam = PK11_ParamFromIV(wrapMech, &ivItem); + if (!ivParam) { + NS_WARNING("Couldn't create IV param"); + rv = NS_ERROR_FAILURE; + goto verify_done; + } + + // Step 3. Unwrap the private key with the key from the passphrase. + slot = PK11_GetInternalSlot(); + if (!slot) { + NS_WARNING("Can't get internal PK11 slot"); + rv = NS_ERROR_FAILURE; + goto verify_done; + } + + keyID = &ivItem; + privKey = PK11_UnwrapPrivKey(slot, + pbeKey, wrapMech, ivParam, &wrappedPrivKey, + nsnull, + keyID, + PR_FALSE, + PR_TRUE, + CKK_RSA, + privKeyUsage, privKeyUsageLength, + nsnull); + if (!privKey) { + NS_WARNING("PK11_UnwrapPrivKey failed"); + } else { + *result = PR_TRUE; + } + +verify_done: + if (privKey) + SECKEY_DestroyPrivateKey(privKey); + if (pbeKey) + PK11_FreeSymKey(pbeKey); + if (slot) + PK11_FreeSlot(slot); + if (ivParam) + SECITEM_FreeItem(ivParam, PR_TRUE); + + return rv; +} diff --git a/services/crypto/components/IWeaveCrypto.xpt b/services/crypto/components/IWeaveCrypto.xpt index 0962806b3443265ac2ff92deac91a390b442f80a..2ed7438b519b70a0a5bc2ab3444d9d0e404b96bc 100644 GIT binary patch delta 309 zcmbQpa+76(IAi2QiP(C+1_lO3cE$uY1~vyEOOUYv$O4H;!^PCWVhlhrW0r>P4Lcfk ztk}W82I5<@fOtUub_m~@6~gb>(E(Kv%m`DP3TKruHL$@%>${kd4V=veF#uU?9Tu_u zP>ULNBya((W&yh80?0*kfQ-8!#ttCkC5W*L$oL9k>}g2MNzX6JEXl}aK(HqJGEP=3 pN-Zx+EC?vdEK4j&^-is1C`&EMOsfn?EG{m{C`v3&oqV6s2mmB@SsMTV delta 211 zcmcb~GLdD1IHTZ1iP(Cc1_lO(hl~kq3~UZS)@#NFAPXe+6(+{W2o?hhG4irBY;V}n zuw%sz1~w31lm)~C^0!0yvaAq($BquD3SCB+T6;JvfT@8EE}FuOY+xxH!~nP$3(%Gh ckX>_tjHw{T4j^M8h_MUESUWiqh&7lD0sjFrm;e9( diff --git a/services/crypto/platform/Darwin/components/WeaveCrypto.dylib b/services/crypto/platform/Darwin/components/WeaveCrypto.dylib index a7ac2d1bb3410738e66d3ef638cde884cfe961d6..c1cd643278a53a75787c97f19758c3b10df1a2fe 100755 GIT binary patch delta 10084 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 delta 8153 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 diff --git a/services/sync/tests/unit/test_crypto_rewrap.js b/services/sync/tests/unit/test_crypto_rewrap.js new file mode 100644 index 00000000000..a8ecde0e358 --- /dev/null +++ b/services/sync/tests/unit/test_crypto_rewrap.js @@ -0,0 +1,35 @@ +function run_test() { + var cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]. + getService(Ci.IWeaveCrypto); + + var salt = cryptoSvc.generateRandomBytes(16); + var iv = cryptoSvc.generateRandomIV(); + var symKey = cryptoSvc.generateRandomKey(); + + // Tests with a 2048 bit key (the default) + do_check_eq(cryptoSvc.keypairBits, 2048) + var pubOut = {}; + var privOut = {}; + cryptoSvc.generateKeypair("old passphrase", salt, iv, pubOut, privOut); + var pubKey = pubOut.value; + var privKey = privOut.value; + + // do some key wrapping + var wrappedKey = cryptoSvc.wrapSymmetricKey(symKey, pubKey); + var unwrappedKey = cryptoSvc.unwrapSymmetricKey(wrappedKey, privKey, + "old passphrase", salt, iv); + + // Is our unwrapped key the same thing we started with? + do_check_eq(unwrappedKey, symKey); + + // Rewrap key with a new passphrase + var newPrivKey = cryptoSvc.rewrapPrivateKey(privKey, "old passphrase", + salt, iv, "new passphrase"); + + // Unwrap symkey with new symkey + var newUnwrappedKey = cryptoSvc.unwrapSymmetricKey(wrappedKey, newPrivKey, + "new passphrase", salt, iv); + + // The acid test... Is this unwrapped symkey the same as before? + do_check_eq(newUnwrappedKey, unwrappedKey); +} diff --git a/services/sync/tests/unit/test_crypto_verify.js b/services/sync/tests/unit/test_crypto_verify.js new file mode 100644 index 00000000000..f55f7c004d1 --- /dev/null +++ b/services/sync/tests/unit/test_crypto_verify.js @@ -0,0 +1,23 @@ +function run_test() { + var cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]. + getService(Ci.IWeaveCrypto); + + var salt = cryptoSvc.generateRandomBytes(16); + var iv = cryptoSvc.generateRandomIV(); + + // Tests with a 2048 bit key (the default) + do_check_eq(cryptoSvc.keypairBits, 2048) + var privOut = {}; + cryptoSvc.generateKeypair("passphrase", salt, iv, {}, privOut); + var privKey = privOut.value; + + // Check with correct passphrase + var shouldBeTrue = cryptoSvc.verifyPassphrase(privKey, "passphrase", + salt, iv); + do_check_eq(shouldBeTrue, true); + + // Check with incorrect passphrase + var shouldBeFalse = cryptoSvc.verifyPassphrase(privKey, "NotPassphrase", + salt, iv); + do_check_eq(shouldBeFalse, false); +}