Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(331)

Side by Side Diff: chrome/browser/importer/nss_decryptor_linux.cc

Issue 160077: Linux: Fix NSSDecryptor to import Firefox passwords from the user database correctly. (Closed)
Patch Set: Add comments. Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/importer/nss_decryptor_linux.h" 5 #include "chrome/browser/importer/nss_decryptor_linux.h"
6 6
7 #include <pk11pub.h>
8 #include <pk11sdr.h>
9
10 #include "base/basictypes.h"
7 #include "base/nss_init.h" 11 #include "base/nss_init.h"
8 12 #include "base/string_util.h"
9 NSSDecryptor::NSSDecryptor() : is_nss_initialized_(false) {} 13 #include "base/sys_string_conversions.h"
10 NSSDecryptor::~NSSDecryptor() {} 14
15 NSSDecryptor::NSSDecryptor() : is_nss_initialized_(false), db_slot_(NULL) {}
16 NSSDecryptor::~NSSDecryptor() {
17 if (db_slot_) {
18 // Deliberately leave the user db open, just in case we need to open more
19 // than one, because there's an NSS bug with reopening user dbs.
20 // https://bugzilla.mozilla.org/show_bug.cgi?id=506140
21 // SECMOD_CloseUserDB(db_slot_);
22 PK11_FreeSlot(db_slot_);
23 }
24 }
11 25
12 bool NSSDecryptor::Init(const std::wstring& /* dll_path */, 26 bool NSSDecryptor::Init(const std::wstring& /* dll_path */,
13 const std::wstring& /* db_path */) { 27 const std::wstring& db_path) {
14 base::EnsureNSSInit(); 28 base::EnsureNSSInit();
15 is_nss_initialized_ = true; 29 is_nss_initialized_ = true;
16 return true; 30 const std::string modspec =
17 } 31 StringPrintf("configDir='%s' tokenDescription='Firefox NSS database' "
32 "flags=readOnly", base::SysWideToNativeMB(db_path).c_str());
33 db_slot_ = SECMOD_OpenUserDB(modspec.c_str());
34 return db_slot_ != NULL;
35 }
36
37 // This method is based on some NSS code in
38 // security/nss/lib/pk11wrap/pk11sdr.c
39 // This code is copied because the implementation assumes the use of the
40 // internal key slot for decryption, but we need to use another slot.
41 // The license block is:
42 /* ***** BEGIN LICENSE BLOCK *****
43 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
44 *
45 * The contents of this file are subject to the Mozilla Public License Version
46 * 1.1 (the "License"); you may not use this file except in compliance with
47 * the License. You may obtain a copy of the License at
48 * http://www.mozilla.org/MPL/
49 *
50 * Software distributed under the License is distributed on an "AS IS" basis,
51 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
52 * for the specific language governing rights and limitations under the
53 * License.
54 *
55 * The Original Code is the Netscape security libraries.
56 *
57 * The Initial Developer of the Original Code is
58 * Netscape Communications Corporation.
59 * Portions created by the Initial Developer are Copyright (C) 1994-2000
60 * the Initial Developer. All Rights Reserved.
61 *
62 * Contributor(s):
63 * thayes@netscape.com
64 *
65 * Alternatively, the contents of this file may be used under the terms of
66 * either the GNU General Public License Version 2 or later (the "GPL"), or
67 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
68 * in which case the provisions of the GPL or the LGPL are applicable instead
69 * of those above. If you wish to allow use of your version of this file only
70 * under the terms of either the GPL or the LGPL, and not to allow others to
71 * use your version of this file under the terms of the MPL, indicate your
72 * decision by deleting the provisions above and replace them with the notice
73 * and other provisions required by the GPL or the LGPL. If you do not delete
74 * the provisions above, a recipient may use your version of this file under
75 * the terms of any one of the MPL, the GPL or the LGPL.
76 *
77 * ***** END LICENSE BLOCK ***** */
78
79 /*
80 * Data structure and template for encoding the result of an SDR operation
81 * This is temporary. It should include the algorithm ID of the encryption
82 * mechanism
83 */
84 struct SDRResult
85 {
86 SECItem keyid;
87 SECAlgorithmID alg;
88 SECItem data;
89 };
90 typedef struct SDRResult SDRResult;
91
92 static SEC_ASN1Template g_template[] = {
93 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (SDRResult) },
94 { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) },
95 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SDRResult, alg),
96 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
97 { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) },
98 { 0 }
99 };
100
101 static SECStatus
102 unpadBlock(SECItem *data, int blockSize, SECItem *result)
103 {
104 SECStatus rv = SECSuccess;
105 int padLength;
106 int i;
107
108 result->data = 0;
109 result->len = 0;
110
111 /* Remove the padding from the end if the input data */
112 if (data->len == 0 || data->len % blockSize != 0) { rv = SECFailure; goto los er; }
113
114 padLength = data->data[data->len-1];
115 if (padLength > blockSize) { rv = SECFailure; goto loser; }
116
117 /* verify padding */
118 for (i=data->len - padLength; static_cast<uint32>(i) < data->len; i++) {
119 if (data->data[i] != padLength) {
120 rv = SECFailure;
121 goto loser;
122 }
123 }
124
125 result->len = data->len - padLength;
126 result->data = (unsigned char *)PORT_Alloc(result->len);
127 if (!result->data) { rv = SECFailure; goto loser; }
128
129 PORT_Memcpy(result->data, data->data, result->len);
130
131 if (padLength < 2) {
132 return SECWouldBlock;
133 }
134
135 loser:
136 return rv;
137 }
138
139 /* decrypt a block */
140 static SECStatus
141 pk11Decrypt(PK11SlotInfo *slot, PLArenaPool *arena,
142 CK_MECHANISM_TYPE type, PK11SymKey *key,
143 SECItem *params, SECItem *in, SECItem *result)
144 {
145 PK11Context *ctx = 0;
146 SECItem paddedResult;
147 SECStatus rv;
148
149 paddedResult.len = 0;
150 paddedResult.data = 0;
151
152 ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params);
153 if (!ctx) { rv = SECFailure; goto loser; }
154
155 paddedResult.len = in->len;
156 paddedResult.data = static_cast<unsigned char*>(
157 PORT_ArenaAlloc(arena, paddedResult.len));
158
159 rv = PK11_CipherOp(ctx, paddedResult.data,
160 (int*)&paddedResult.len, paddedResult.len,
161 in->data, in->len);
162 if (rv != SECSuccess) goto loser;
163
164 PK11_Finalize(ctx);
165
166 /* Remove the padding */
167 rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result);
168 if (rv) goto loser;
169
170 loser:
171 if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
172 return rv;
173 }
174
175 SECStatus NSSDecryptor::PK11SDR_DecryptWithSlot(
176 PK11SlotInfo* slot, SECItem* data, SECItem* result, void* cx) const {
177 SECStatus rv = SECSuccess;
178 PK11SymKey *key = 0;
179 CK_MECHANISM_TYPE type;
180 SDRResult sdrResult;
181 SECItem *params = 0;
182 SECItem possibleResult = { static_cast<SECItemType>(0), NULL, 0 };
183 PLArenaPool *arena = 0;
184
185 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
186 if (!arena) { rv = SECFailure; goto loser; }
187
188 /* Decode the incoming data */
189 memset(&sdrResult, 0, sizeof sdrResult);
190 rv = SEC_QuickDERDecodeItem(arena, &sdrResult, g_template, data);
191 if (rv != SECSuccess) goto loser; /* Invalid format */
192
193 /* Get the parameter values from the data */
194 params = PK11_ParamFromAlgid(&sdrResult.alg);
195 if (!params) { rv = SECFailure; goto loser; }
196
197 /* Use triple-DES (Should look up the algorithm) */
198 type = CKM_DES3_CBC;
199 key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx);
200 if (!key) {
201 rv = SECFailure;
202 } else {
203 rv = pk11Decrypt(slot, arena, type, key, params,
204 &sdrResult.data, result);
205 }
206
207 loser:
208 if (arena) PORT_FreeArena(arena, PR_TRUE);
209 if (key) PK11_FreeSymKey(key);
210 if (params) SECITEM_ZfreeItem(params, PR_TRUE);
211 if (possibleResult.data) SECITEM_ZfreeItem(&possibleResult, PR_FALSE);
212
213 return rv;
214 }
OLDNEW
« no previous file with comments | « chrome/browser/importer/nss_decryptor_linux.h ('k') | chrome/browser/importer/nss_decryptor_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698