Bug 1275841 - Make nsISecretDecoderRing.idl encryptString() and decryptString() use the Mozilla string classes. r=keeler draft
authorCykesiopka <cykesiopka.bmo@gmail.com>
Fri, 19 Aug 2016 09:37:48 +0800
changeset 403073 05d4b673c1db79652c33c385db229168b427e16c
parent 403072 d7275e33bfe9160ea38be18ead6a3f25b3699a6c
child 528819 90b3bb144ba90235550030e63d2a47b40bb79aa8
push id26817
push usercykesiopka.bmo@gmail.com
push dateFri, 19 Aug 2016 03:03:31 +0000
reviewerskeeler
bugs1275841
milestone51.0a1
Bug 1275841 - Make nsISecretDecoderRing.idl encryptString() and decryptString() use the Mozilla string classes. r=keeler The Mozilla string classes don't require manual memory management and automatically keep track of length, making them a safer choice than raw C strings. MozReview-Commit-ID: EwCiiP9EhDr
security/manager/ssl/SecretDecoderRing.cpp
security/manager/ssl/SecretDecoderRing.h
security/manager/ssl/nsISecretDecoderRing.idl
--- a/security/manager/ssl/SecretDecoderRing.cpp
+++ b/security/manager/ssl/SecretDecoderRing.cpp
@@ -6,32 +6,26 @@
 
 #include "SecretDecoderRing.h"
 
 #include "ScopedNSSTypes.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "mozilla/Services.h"
 #include "nsCOMPtr.h"
-#include "nsCRT.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsITokenPasswordDialogs.h"
-#include "nsMemory.h"
 #include "nsNSSComponent.h"
 #include "nsNSSHelper.h"
-#include "nsString.h"
-#include "nsThreadUtils.h"
 #include "pk11func.h"
 #include "pk11sdr.h" // For PK11SDR_Encrypt, PK11SDR_Decrypt
-#include "plstr.h"
 #include "ssl.h" // For SSL_ClearSessionCache
-#include "stdlib.h"
 
 using namespace mozilla;
 
 // NOTE: Should these be the thread-safe versions?
 NS_IMPL_ISUPPORTS(SecretDecoderRing, nsISecretDecoderRing)
 
 SecretDecoderRing::SecretDecoderRing()
 {
@@ -43,163 +37,122 @@ SecretDecoderRing::~SecretDecoderRing()
   if (isAlreadyShutDown()) {
     return;
   }
 
   shutdown(calledFromObject);
 }
 
 nsresult
-SecretDecoderRing::Encrypt(unsigned char* data, uint32_t dataLen,
-                   /*out*/ unsigned char** result, /*out*/ uint32_t* resultLen)
+SecretDecoderRing::Encrypt(const nsACString& data, /*out*/ nsACString& result)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
-
   UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
   if (!slot) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   /* Make sure token is initialized. */
+  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
   nsresult rv = setPassword(slot.get(), ctx, locker);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   /* Force authentication */
   if (PK11_Authenticate(slot.get(), true, ctx) != SECSuccess) {
     return NS_ERROR_FAILURE;
   }
 
   /* Use default key id */
   SECItem keyid;
   keyid.data = nullptr;
   keyid.len = 0;
   SECItem request;
-  request.data = data;
-  request.len = dataLen;
-  SECItem reply;
-  reply.data = nullptr;
-  reply.len = 0;
+  request.data = BitwiseCast<unsigned char*, const char*>(data.BeginReading());
+  request.len = data.Length();
+  ScopedAutoSECItem reply;
   if (PK11SDR_Encrypt(&keyid, &request, &reply, ctx) != SECSuccess) {
     return NS_ERROR_FAILURE;
   }
 
-  *result = reply.data;
-  *resultLen = reply.len;
-
+  result.Assign(BitwiseCast<char*, unsigned char*>(reply.data), reply.len);
   return NS_OK;
 }
 
 nsresult
-SecretDecoderRing::Decrypt(unsigned char* data, uint32_t dataLen,
-                   /*out*/ unsigned char** result, /*out*/ uint32_t* resultLen)
+SecretDecoderRing::Decrypt(const nsACString& data, /*out*/ nsACString& result)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
-
-  *result = nullptr;
-  *resultLen = 0;
-
   /* Find token with SDR key */
   UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
   if (!slot) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   /* Force authentication */
+  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
   if (PK11_Authenticate(slot.get(), true, ctx) != SECSuccess) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   SECItem request;
-  request.data = data;
-  request.len = dataLen;
-  SECItem reply;
-  reply.data = nullptr;
-  reply.len = 0;
+  request.data = BitwiseCast<unsigned char*, const char*>(data.BeginReading());
+  request.len = data.Length();
+  ScopedAutoSECItem reply;
   if (PK11SDR_Decrypt(&request, &reply, ctx) != SECSuccess) {
     return NS_ERROR_FAILURE;
   }
 
-  *result = reply.data;
-  *resultLen = reply.len;
+  result.Assign(BitwiseCast<char*, unsigned char*>(reply.data), reply.len);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+SecretDecoderRing::EncryptString(const nsACString& text,
+                         /*out*/ nsACString& encryptedBase64Text)
+{
+  nsAutoCString encryptedText;
+  nsresult rv = Encrypt(text, encryptedText);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  rv = Base64Encode(encryptedText, encryptedBase64Text);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-SecretDecoderRing::EncryptString(const char* text, char** _retval)
+SecretDecoderRing::DecryptString(const nsACString& encryptedBase64Text,
+                         /*out*/ nsACString& decryptedText)
 {
-  nsresult rv = NS_OK;
-  unsigned char *encrypted = 0;
-  uint32_t eLen = 0;
-
-  if (!text || !_retval) {
-    rv = NS_ERROR_INVALID_POINTER;
-    goto loser;
+  nsAutoCString encryptedText;
+  nsresult rv = Base64Decode(encryptedBase64Text, encryptedText);
+  if (NS_FAILED(rv)) {
+    return rv;
   }
 
-  rv = Encrypt((unsigned char *)text, strlen(text), &encrypted, &eLen);
-  if (rv != NS_OK) { goto loser; }
-
-  rv = Base64Encode(BitwiseCast<const char*>(encrypted), eLen, _retval);
-
-loser:
-  if (encrypted) PORT_Free(encrypted);
-
-  return rv;
-}
-
-NS_IMETHODIMP
-SecretDecoderRing::DecryptString(const char* crypt, char** _retval)
-{
-  nsresult rv = NS_OK;
-  char *r = 0;
-  unsigned char *decoded = 0;
-  uint32_t decodedLen = 0;
-  unsigned char *decrypted = 0;
-  uint32_t decryptedLen = 0;
-
-  if (!crypt || !_retval) {
-    rv = NS_ERROR_INVALID_POINTER;
-    goto loser;
+  rv = Decrypt(encryptedText, decryptedText);
+  if (NS_FAILED(rv)) {
+    return rv;
   }
 
-  rv = Base64Decode(crypt, strlen(crypt), BitwiseCast<char**>(&decoded),
-                    &decodedLen);
-  if (NS_FAILED(rv)) goto loser;
-
-  rv = Decrypt(decoded, decodedLen, &decrypted, &decryptedLen);
-  if (rv != NS_OK) goto loser;
-
-  // Convert to NUL-terminated string
-  r = (char *)moz_xmalloc(decryptedLen+1);
-  if (!r) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
-
-  memcpy(r, decrypted, decryptedLen);
-  r[decryptedLen] = 0;
-
-  *_retval = r;
-  r = 0;
-
-loser:
-  if (decrypted) PORT_Free(decrypted);
-  if (decoded) free(decoded);
-
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 SecretDecoderRing::ChangePassword()
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
--- a/security/manager/ssl/SecretDecoderRing.h
+++ b/security/manager/ssl/SecretDecoderRing.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef SecretDecoderRing_h
 #define SecretDecoderRing_h
 
 #include "nsISecretDecoderRing.h"
 #include "nsNSSShutDown.h"
+#include "nsString.h"
 
 #define NS_SECRETDECODERRING_CONTRACTID "@mozilla.org/security/sdr;1"
 
 #define NS_SECRETDECODERRING_CID \
   { 0x0c4f1ddc, 0x1dd2, 0x11b2, { 0x9d, 0x95, 0xf2, 0xfd, 0xf1, 0x13, 0x04, 0x4b } }
 
 class SecretDecoderRing : public nsISecretDecoderRing
                         , public nsNSSShutDownObject
@@ -26,15 +27,13 @@ public:
 
   // Nothing to release.
   virtual void virtualDestroyNSSReference() override {}
 
 protected:
   virtual ~SecretDecoderRing();
 
 private:
-  nsresult Encrypt(unsigned char* data, uint32_t dataLen,
-                   /*out*/ unsigned char** result, /*out*/ uint32_t* resultLen);
-  nsresult Decrypt(unsigned char* data, uint32_t dataLen,
-                   /*out*/ unsigned char** result, /*out*/ uint32_t* resultLen);
+  nsresult Encrypt(const nsACString& data, /*out*/ nsACString& result);
+  nsresult Decrypt(const nsACString& data, /*out*/ nsACString& result);
 };
 
 #endif // SecretDecoderRing_h
--- a/security/manager/ssl/nsISecretDecoderRing.idl
+++ b/security/manager/ssl/nsISecretDecoderRing.idl
@@ -3,25 +3,30 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 [scriptable, uuid(0EC80360-075C-11d4-9FD4-00C04F1B83D8)]
 interface nsISecretDecoderRing: nsISupports {
   /**
-   * Encrypt nul-terminated string to BASE64 output.
+   * Encrypt to Base64 output.
+   *
+   * @param text The text to encrypt.
+   * @return The encrypted text, encoded as Base64.
    */
-  string encryptString(in string text);
+  ACString encryptString(in AUTF8String text);
 
   /**
-   * Decrypt BASE64 input to nul-terminated string output.  There is
-   * no check for embedded nul values in the decrypted output.
+   * Decrypt Base64 input.
+   *
+   * @param encryptedBase64Text Encrypted input text, encoded as Base64.
+   * @return The decoded text.
    */
-  string decryptString(in string crypt);
+  AUTF8String decryptString(in ACString encryptedBase64Text);
 
   /**
    * Prompt the user to change the password on the SDR key.
    */
   void changePassword();
 
   /**
    * Logout of the security device that protects the SDR key.