15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/utility/importer/nss_decryptor_system_nss.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11sdr.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSDecryptor::NSSDecryptor() : is_nss_initialized_(false), db_slot_(NULL) {} 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSDecryptor::~NSSDecryptor() { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_slot_) { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deliberately leave the user db open, just in case we need to open more 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // than one, because there's an NSS bug with reopening user dbs. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // https://bugzilla.mozilla.org/show_bug.cgi?id=506140 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SECMOD_CloseUserDB(db_slot_); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11_FreeSlot(db_slot_); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NSSDecryptor::Init(const base::FilePath& dll_path, 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& db_path) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::EnsureNSSInit(); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_nss_initialized_ = true; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string modspec = 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf( 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "configDir='%s' tokenDescription='Firefox NSS database' " 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "flags=readOnly", 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_path.value().c_str()); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_slot_ = SECMOD_OpenUserDB(modspec.c_str()); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_slot_ != NULL; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is based on some NSS code in 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// security/nss/lib/pk11wrap/pk11sdr.c, CVS revision 1.22 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code is copied because the implementation assumes the use of the 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// internal key slot for decryption, but we need to use another slot. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The license block is: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ***** BEGIN LICENSE BLOCK ***** 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: MPL 1.1/GPL 2.0/LGPL 2.1 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The contents of this file are subject to the Mozilla Public License Version 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (the "License"); you may not use this file except in compliance with 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the License. You may obtain a copy of the License at 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.mozilla.org/MPL/ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software distributed under the License is distributed on an "AS IS" basis, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for the specific language governing rights and limitations under the 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Original Code is the Netscape security libraries. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Initial Developer of the Original Code is 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Netscape Communications Corporation. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Portions created by the Initial Developer are Copyright (C) 1994-2000 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Initial Developer. All Rights Reserved. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Contributor(s): 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * thayes@netscape.com 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, the contents of this file may be used under the terms of 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * either the GNU General Public License Version 2 or later (the "GPL"), or 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in which case the provisions of the GPL or the LGPL are applicable instead 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of those above. If you wish to allow use of your version of this file only 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the terms of either the GPL or the LGPL, and not to allow others to 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use your version of this file under the terms of the MPL, indicate your 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decision by deleting the provisions above and replace them with the notice 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and other provisions required by the GPL or the LGPL. If you do not delete 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the provisions above, a recipient may use your version of this file under 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the terms of any one of the MPL, the GPL or the LGPL. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ***** END LICENSE BLOCK ***** */ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Data structure and template for encoding the result of an SDR operation 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This is temporary. It should include the algorithm ID of the encryption 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * mechanism 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SDRResult 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem keyid; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECAlgorithmID alg; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem data; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct SDRResult SDRResult; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SEC_ASN1Template g_template[] = { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (SDRResult) }, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) }, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SDRResult, alg), 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) }, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 0 } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unpadBlock(SECItem *data, int blockSize, SECItem *result) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = SECSuccess; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int padLength; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->data = 0; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->len = 0; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove the padding from the end if the input data */ 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data->len == 0 || data->len % blockSize != 0) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = SECFailure; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto loser; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) padLength = data->data[data->len-1]; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (padLength > blockSize) { rv = SECFailure; goto loser; } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* verify padding */ 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=data->len - padLength; static_cast<uint32>(i) < data->len; i++) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data->data[i] != padLength) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = SECFailure; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto loser; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->len = data->len - padLength; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->data = (unsigned char *)PORT_Alloc(result->len); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result->data) { rv = SECFailure; goto loser; } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_Memcpy(result->data, data->data, result->len); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (padLength < 2) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SECWouldBlock; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* decrypt a block */ 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pk11Decrypt(PK11SlotInfo *slot, PLArenaPool *arena, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_MECHANISM_TYPE type, PK11SymKey *key, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem *params, SECItem *in, SECItem *result) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11Context *ctx = 0; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem paddedResult; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paddedResult.len = 0; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paddedResult.data = 0; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ctx) { rv = SECFailure; goto loser; } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paddedResult.len = in->len; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paddedResult.data = static_cast<unsigned char*>( 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_ArenaAlloc(arena, paddedResult.len)); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = PK11_CipherOp(ctx, paddedResult.data, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int*)&paddedResult.len, paddedResult.len, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in->data, in->len); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) goto loser; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11_Finalize(ctx); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove the padding */ 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv) goto loser; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser: 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ctx) PK11_DestroyContext(ctx, PR_TRUE); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus NSSDecryptor::PK11SDR_DecryptWithSlot( 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SlotInfo* slot, SECItem* data, SECItem* result, void* cx) const { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = SECSuccess; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SymKey *key = 0; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_MECHANISM_TYPE type; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SDRResult sdrResult; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem *params = 0; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem possibleResult = { siBuffer, NULL, 0 }; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLArenaPool *arena = 0; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!arena) { rv = SECFailure; goto loser; } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Decode the incoming data */ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&sdrResult, 0, sizeof sdrResult); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = SEC_QuickDERDecodeItem(arena, &sdrResult, g_template, data); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) goto loser; /* Invalid format */ 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get the parameter values from the data */ 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params = PK11_ParamFromAlgid(&sdrResult.alg); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!params) { rv = SECFailure; goto loser; } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Use triple-DES (Should look up the algorithm) */ 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type = CKM_DES3_CBC; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!key) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = SECFailure; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = pk11Decrypt(slot, arena, type, key, params, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sdrResult.data, result); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if the pad value was too small (1 or 2), then it's statistically 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'likely' that (1 in 256) that we may not have the correct key. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Check the other keys for a better match. If we find none, use 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this result. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == SECWouldBlock) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) possibleResult = *result; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * handle the case where your key indicies may have been broken 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SymKey *keyList = PK11_ListFixedKeysInSlot(slot, NULL, cx); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SymKey *testKey = NULL; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SymKey *nextKey = NULL; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (testKey = keyList; testKey; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testKey = PK11_GetNextSymKey(testKey)) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = pk11Decrypt(slot, arena, type, testKey, params, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sdrResult.data, result); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == SECSuccess) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* found a close match. If it's our first remember it */ 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == SECWouldBlock) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (possibleResult.data) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this is unlikely but possible. If we hit this condition, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we have no way of knowing which possibility to prefer. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in this case we just match the key the application 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * thought was the right one */ 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECITEM_ZfreeItem(result, PR_FALSE); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) possibleResult = *result; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* free the list */ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (testKey = keyList; testKey; testKey = nextKey) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nextKey = PK11_GetNextSymKey(testKey); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11_FreeSymKey(testKey); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we didn't find a better key, use the one with a small pad value */ 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((rv != SECSuccess) && (possibleResult.data)) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = possibleResult; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) possibleResult.data = NULL; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = SECSuccess; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loser: 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (arena) PORT_FreeArena(arena, PR_TRUE); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key) PK11_FreeSymKey(key); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params) SECITEM_ZfreeItem(params, PR_TRUE); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (possibleResult.data) SECITEM_ZfreeItem(&possibleResult, PR_FALSE); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 273