1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/src/nsStreamCipher.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,186 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsIKeyModule.h" 1.9 +#include "nsStreamCipher.h" 1.10 +#include "nsStreamUtils.h" 1.11 +#include "base64.h" 1.12 + 1.13 +NS_IMPL_ISUPPORTS(nsStreamCipher, nsIStreamCipher) 1.14 + 1.15 +nsStreamCipher::nsStreamCipher() 1.16 + : mContext(nullptr) 1.17 +{ 1.18 +} 1.19 + 1.20 +nsStreamCipher::~nsStreamCipher() 1.21 +{ 1.22 + if (mContext) 1.23 + PK11_DestroyContext(mContext, true /* free sub-objects */); 1.24 +} 1.25 + 1.26 +nsresult 1.27 +nsStreamCipher::InitWithIV_(nsIKeyObject *aKey, SECItem* aIV) 1.28 +{ 1.29 + NS_ENSURE_ARG_POINTER(aKey); 1.30 + 1.31 + // Make sure we have a SYM_KEY. 1.32 + int16_t keyType; 1.33 + nsresult rv = aKey->GetType(&keyType); 1.34 + NS_ENSURE_SUCCESS(rv, rv); 1.35 + if (keyType != nsIKeyObject::SYM_KEY) 1.36 + return NS_ERROR_INVALID_ARG; 1.37 + 1.38 + if (mContext) 1.39 + PK11_DestroyContext(mContext, true /* free sub-objects */); 1.40 + 1.41 + // Get the PK11SymKey out of the key object and create the PK11Context. 1.42 + void* keyObj; 1.43 + rv = aKey->GetKeyObj(&keyObj); 1.44 + NS_ENSURE_SUCCESS(rv, rv); 1.45 + 1.46 + PK11SymKey *symkey = reinterpret_cast<PK11SymKey*>(keyObj); 1.47 + if (!symkey) 1.48 + return NS_ERROR_FAILURE; 1.49 + 1.50 + CK_MECHANISM_TYPE cipherMech = PK11_GetMechanism(symkey); 1.51 + 1.52 + SECItem *param = nullptr; 1.53 + // aIV may be null 1.54 + param = PK11_ParamFromIV(cipherMech, aIV); 1.55 + if (!param) 1.56 + return NS_ERROR_FAILURE; 1.57 + 1.58 + mContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, 1.59 + symkey, param); 1.60 + 1.61 + SECITEM_FreeItem(param, true); 1.62 + 1.63 + // Something went wrong if mContext doesn't exist. 1.64 + if (!mContext) 1.65 + return NS_ERROR_FAILURE; 1.66 + 1.67 + // Everything went ok. 1.68 + mValue.Truncate(); 1.69 + return NS_OK; 1.70 +} 1.71 + 1.72 +///////////////////////////////////////////////////////////////////////////// 1.73 +// nsIStreamCipher 1.74 + 1.75 +NS_IMETHODIMP nsStreamCipher::Init(nsIKeyObject *aKey) 1.76 +{ 1.77 + return InitWithIV_(aKey, nullptr); 1.78 +} 1.79 + 1.80 +NS_IMETHODIMP nsStreamCipher::InitWithIV(nsIKeyObject *aKey, 1.81 + const uint8_t *aIV, uint32_t aIVLen) 1.82 +{ 1.83 + SECItem IV; 1.84 + IV.data = (unsigned char*)aIV; 1.85 + IV.len = aIVLen; 1.86 + return InitWithIV_(aKey, &IV); 1.87 +} 1.88 + 1.89 +NS_IMETHODIMP nsStreamCipher::Update(const uint8_t *aData, uint32_t aLen) 1.90 +{ 1.91 + if (!mContext) 1.92 + return NS_ERROR_NOT_INITIALIZED; 1.93 + 1.94 + unsigned char* output = new unsigned char[aLen]; 1.95 + unsigned char* input = (unsigned char*)aData; 1.96 + 1.97 + int32_t setLen; 1.98 + 1.99 +#ifdef DEBUG 1.100 + SECStatus rv = 1.101 +#endif 1.102 + PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen); 1.103 + NS_ASSERTION(rv == SECSuccess, "failed to encrypt"); 1.104 + NS_ASSERTION((uint32_t)setLen == aLen, "data length should not change"); 1.105 + 1.106 + mValue.Append((const char*)output, aLen); 1.107 + 1.108 + delete [] output; 1.109 + 1.110 + return NS_OK; 1.111 +} 1.112 + 1.113 +NS_IMETHODIMP nsStreamCipher::UpdateFromStream(nsIInputStream *aStream, 1.114 + int32_t aLen) 1.115 +{ 1.116 + if (!mContext) 1.117 + return NS_ERROR_NOT_INITIALIZED; 1.118 + 1.119 + nsCString inputString; 1.120 + nsresult rv = NS_ConsumeStream(aStream, aLen, inputString); 1.121 + NS_ENSURE_SUCCESS(rv, rv); 1.122 + 1.123 + return UpdateFromString(inputString); 1.124 +} 1.125 + 1.126 +NS_IMETHODIMP nsStreamCipher::UpdateFromString(const nsACString& aInput) 1.127 +{ 1.128 + if (!mContext) 1.129 + return NS_ERROR_NOT_INITIALIZED; 1.130 + 1.131 + const nsCString& flatInput = PromiseFlatCString(aInput); 1.132 + unsigned char* input = (unsigned char*)flatInput.get(); 1.133 + uint32_t len = aInput.Length(); 1.134 + 1.135 + unsigned char* output = new unsigned char[len]; 1.136 + 1.137 + int32_t setLen; 1.138 + 1.139 +#ifdef DEBUG 1.140 + SECStatus rv = 1.141 +#endif 1.142 + PK11_CipherOp(mContext, output, &setLen, len, input, len); 1.143 + NS_ASSERTION(rv == SECSuccess, "failed to encrypt"); 1.144 + NS_ASSERTION((uint32_t)setLen == len, "data length should not change"); 1.145 + 1.146 + mValue.Append((const char*)output, len); 1.147 + delete [] output; 1.148 + 1.149 + return NS_OK; 1.150 +} 1.151 + 1.152 +NS_IMETHODIMP nsStreamCipher::Finish(bool aASCII, nsACString & _retval) 1.153 +{ 1.154 + if (!mContext) 1.155 + return NS_ERROR_NOT_INITIALIZED; 1.156 + 1.157 + if (aASCII) { 1.158 + char *asciiData = BTOA_DataToAscii((unsigned char*)(mValue.get()), 1.159 + mValue.Length()); 1.160 + _retval.Assign(asciiData); 1.161 + PORT_Free(asciiData); 1.162 + } else { 1.163 + _retval.Assign(mValue); 1.164 + } 1.165 + 1.166 + return NS_OK; 1.167 +} 1.168 + 1.169 +NS_IMETHODIMP nsStreamCipher::Discard(int32_t aLen) 1.170 +{ 1.171 + if (!mContext) 1.172 + return NS_ERROR_NOT_INITIALIZED; 1.173 + 1.174 + unsigned char* output = new unsigned char[aLen]; 1.175 + unsigned char* input = new unsigned char[aLen]; 1.176 + 1.177 + int32_t setLen; 1.178 + 1.179 +#ifdef DEBUG 1.180 + SECStatus rv = 1.181 +#endif 1.182 + PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen); 1.183 + NS_ASSERTION(rv == SECSuccess, "failed to encrypt"); 1.184 + NS_ASSERTION(setLen == aLen, "data length should not change"); 1.185 + 1.186 + delete [] output; 1.187 + delete [] input; 1.188 + return NS_OK; 1.189 +}