security/manager/ssl/src/nsStreamCipher.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:94e6a25e951f
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "nsIKeyModule.h"
6 #include "nsStreamCipher.h"
7 #include "nsStreamUtils.h"
8 #include "base64.h"
9
10 NS_IMPL_ISUPPORTS(nsStreamCipher, nsIStreamCipher)
11
12 nsStreamCipher::nsStreamCipher()
13 : mContext(nullptr)
14 {
15 }
16
17 nsStreamCipher::~nsStreamCipher()
18 {
19 if (mContext)
20 PK11_DestroyContext(mContext, true /* free sub-objects */);
21 }
22
23 nsresult
24 nsStreamCipher::InitWithIV_(nsIKeyObject *aKey, SECItem* aIV)
25 {
26 NS_ENSURE_ARG_POINTER(aKey);
27
28 // Make sure we have a SYM_KEY.
29 int16_t keyType;
30 nsresult rv = aKey->GetType(&keyType);
31 NS_ENSURE_SUCCESS(rv, rv);
32 if (keyType != nsIKeyObject::SYM_KEY)
33 return NS_ERROR_INVALID_ARG;
34
35 if (mContext)
36 PK11_DestroyContext(mContext, true /* free sub-objects */);
37
38 // Get the PK11SymKey out of the key object and create the PK11Context.
39 void* keyObj;
40 rv = aKey->GetKeyObj(&keyObj);
41 NS_ENSURE_SUCCESS(rv, rv);
42
43 PK11SymKey *symkey = reinterpret_cast<PK11SymKey*>(keyObj);
44 if (!symkey)
45 return NS_ERROR_FAILURE;
46
47 CK_MECHANISM_TYPE cipherMech = PK11_GetMechanism(symkey);
48
49 SECItem *param = nullptr;
50 // aIV may be null
51 param = PK11_ParamFromIV(cipherMech, aIV);
52 if (!param)
53 return NS_ERROR_FAILURE;
54
55 mContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT,
56 symkey, param);
57
58 SECITEM_FreeItem(param, true);
59
60 // Something went wrong if mContext doesn't exist.
61 if (!mContext)
62 return NS_ERROR_FAILURE;
63
64 // Everything went ok.
65 mValue.Truncate();
66 return NS_OK;
67 }
68
69 /////////////////////////////////////////////////////////////////////////////
70 // nsIStreamCipher
71
72 NS_IMETHODIMP nsStreamCipher::Init(nsIKeyObject *aKey)
73 {
74 return InitWithIV_(aKey, nullptr);
75 }
76
77 NS_IMETHODIMP nsStreamCipher::InitWithIV(nsIKeyObject *aKey,
78 const uint8_t *aIV, uint32_t aIVLen)
79 {
80 SECItem IV;
81 IV.data = (unsigned char*)aIV;
82 IV.len = aIVLen;
83 return InitWithIV_(aKey, &IV);
84 }
85
86 NS_IMETHODIMP nsStreamCipher::Update(const uint8_t *aData, uint32_t aLen)
87 {
88 if (!mContext)
89 return NS_ERROR_NOT_INITIALIZED;
90
91 unsigned char* output = new unsigned char[aLen];
92 unsigned char* input = (unsigned char*)aData;
93
94 int32_t setLen;
95
96 #ifdef DEBUG
97 SECStatus rv =
98 #endif
99 PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen);
100 NS_ASSERTION(rv == SECSuccess, "failed to encrypt");
101 NS_ASSERTION((uint32_t)setLen == aLen, "data length should not change");
102
103 mValue.Append((const char*)output, aLen);
104
105 delete [] output;
106
107 return NS_OK;
108 }
109
110 NS_IMETHODIMP nsStreamCipher::UpdateFromStream(nsIInputStream *aStream,
111 int32_t aLen)
112 {
113 if (!mContext)
114 return NS_ERROR_NOT_INITIALIZED;
115
116 nsCString inputString;
117 nsresult rv = NS_ConsumeStream(aStream, aLen, inputString);
118 NS_ENSURE_SUCCESS(rv, rv);
119
120 return UpdateFromString(inputString);
121 }
122
123 NS_IMETHODIMP nsStreamCipher::UpdateFromString(const nsACString& aInput)
124 {
125 if (!mContext)
126 return NS_ERROR_NOT_INITIALIZED;
127
128 const nsCString& flatInput = PromiseFlatCString(aInput);
129 unsigned char* input = (unsigned char*)flatInput.get();
130 uint32_t len = aInput.Length();
131
132 unsigned char* output = new unsigned char[len];
133
134 int32_t setLen;
135
136 #ifdef DEBUG
137 SECStatus rv =
138 #endif
139 PK11_CipherOp(mContext, output, &setLen, len, input, len);
140 NS_ASSERTION(rv == SECSuccess, "failed to encrypt");
141 NS_ASSERTION((uint32_t)setLen == len, "data length should not change");
142
143 mValue.Append((const char*)output, len);
144 delete [] output;
145
146 return NS_OK;
147 }
148
149 NS_IMETHODIMP nsStreamCipher::Finish(bool aASCII, nsACString & _retval)
150 {
151 if (!mContext)
152 return NS_ERROR_NOT_INITIALIZED;
153
154 if (aASCII) {
155 char *asciiData = BTOA_DataToAscii((unsigned char*)(mValue.get()),
156 mValue.Length());
157 _retval.Assign(asciiData);
158 PORT_Free(asciiData);
159 } else {
160 _retval.Assign(mValue);
161 }
162
163 return NS_OK;
164 }
165
166 NS_IMETHODIMP nsStreamCipher::Discard(int32_t aLen)
167 {
168 if (!mContext)
169 return NS_ERROR_NOT_INITIALIZED;
170
171 unsigned char* output = new unsigned char[aLen];
172 unsigned char* input = new unsigned char[aLen];
173
174 int32_t setLen;
175
176 #ifdef DEBUG
177 SECStatus rv =
178 #endif
179 PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen);
180 NS_ASSERTION(rv == SECSuccess, "failed to encrypt");
181 NS_ASSERTION(setLen == aLen, "data length should not change");
182
183 delete [] output;
184 delete [] input;
185 return NS_OK;
186 }

mercurial