1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/http/des.h" 6 7#include "base/logging.h" 8 9#if defined(USE_OPENSSL) 10#include <openssl/des.h> 11#include "crypto/openssl_util.h" 12#elif defined(USE_NSS) 13#include <nss.h> 14#include <pk11pub.h> 15#include "crypto/nss_util.h" 16#elif defined(OS_MACOSX) 17#include <CommonCrypto/CommonCryptor.h> 18#elif defined(OS_WIN) 19#include <windows.h> 20#include <wincrypt.h> 21#include "crypto/scoped_capi_types.h" 22#endif 23 24// The Mac and Windows (CryptoAPI) versions of DESEncrypt are our own code. 25// DESSetKeyParity, DESMakeKey, and the Linux (NSS) version of DESEncrypt are 26// based on mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, 27// CVS rev. 1.14. 28 29/* ***** BEGIN LICENSE BLOCK ***** 30 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 31 * 32 * The contents of this file are subject to the Mozilla Public License Version 33 * 1.1 (the "License"); you may not use this file except in compliance with 34 * the License. You may obtain a copy of the License at 35 * http://www.mozilla.org/MPL/ 36 * 37 * Software distributed under the License is distributed on an "AS IS" basis, 38 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 39 * for the specific language governing rights and limitations under the 40 * License. 41 * 42 * The Original Code is Mozilla. 43 * 44 * The Initial Developer of the Original Code is IBM Corporation. 45 * Portions created by IBM Corporation are Copyright (C) 2003 46 * IBM Corporation. All Rights Reserved. 47 * 48 * Contributor(s): 49 * Darin Fisher <darin@meer.net> 50 * 51 * Alternatively, the contents of this file may be used under the terms of 52 * either the GNU General Public License Version 2 or later (the "GPL"), or 53 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 54 * in which case the provisions of the GPL or the LGPL are applicable instead 55 * of those above. If you wish to allow use of your version of this file only 56 * under the terms of either the GPL or the LGPL, and not to allow others to 57 * use your version of this file under the terms of the MPL, indicate your 58 * decision by deleting the provisions above and replace them with the notice 59 * and other provisions required by the GPL or the LGPL. If you do not delete 60 * the provisions above, a recipient may use your version of this file under 61 * the terms of any one of the MPL, the GPL or the LGPL. 62 * 63 * ***** END LICENSE BLOCK ***** */ 64 65// Set odd parity bit (in least significant bit position). 66static uint8 DESSetKeyParity(uint8 x) { 67 if ((((x >> 7) ^ (x >> 6) ^ (x >> 5) ^ 68 (x >> 4) ^ (x >> 3) ^ (x >> 2) ^ 69 (x >> 1)) & 0x01) == 0) { 70 x |= 0x01; 71 } else { 72 x &= 0xfe; 73 } 74 return x; 75} 76 77namespace net { 78 79void DESMakeKey(const uint8* raw, uint8* key) { 80 key[0] = DESSetKeyParity(raw[0]); 81 key[1] = DESSetKeyParity((raw[0] << 7) | (raw[1] >> 1)); 82 key[2] = DESSetKeyParity((raw[1] << 6) | (raw[2] >> 2)); 83 key[3] = DESSetKeyParity((raw[2] << 5) | (raw[3] >> 3)); 84 key[4] = DESSetKeyParity((raw[3] << 4) | (raw[4] >> 4)); 85 key[5] = DESSetKeyParity((raw[4] << 3) | (raw[5] >> 5)); 86 key[6] = DESSetKeyParity((raw[5] << 2) | (raw[6] >> 6)); 87 key[7] = DESSetKeyParity((raw[6] << 1)); 88} 89 90#if defined(USE_OPENSSL) 91 92void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 93 crypto::EnsureOpenSSLInit(); 94 95 DES_key_schedule ks; 96 DES_set_key_unchecked( 97 reinterpret_cast<const_DES_cblock*>(const_cast<uint8*>(key)), &ks); 98 99 DES_ecb_encrypt(reinterpret_cast<const_DES_cblock*>(const_cast<uint8*>(src)), 100 reinterpret_cast<DES_cblock*>(hash), &ks, DES_ENCRYPT); 101} 102 103#elif defined(USE_NSS) 104 105void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 106 CK_MECHANISM_TYPE cipher_mech = CKM_DES_ECB; 107 PK11SlotInfo* slot = NULL; 108 PK11SymKey* symkey = NULL; 109 PK11Context* ctxt = NULL; 110 SECItem key_item; 111 SECItem* param = NULL; 112 SECStatus rv; 113 unsigned int n; 114 115 crypto::EnsureNSSInit(); 116 117 slot = PK11_GetInternalSlot(); 118 if (!slot) 119 goto done; 120 121 key_item.data = const_cast<uint8*>(key); 122 key_item.len = 8; 123 symkey = PK11_ImportSymKey(slot, cipher_mech, 124 PK11_OriginUnwrap, CKA_ENCRYPT, 125 &key_item, NULL); 126 if (!symkey) 127 goto done; 128 129 // No initialization vector required. 130 param = PK11_ParamFromIV(cipher_mech, NULL); 131 if (!param) 132 goto done; 133 134 ctxt = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT, 135 symkey, param); 136 if (!ctxt) 137 goto done; 138 139 rv = PK11_CipherOp(ctxt, hash, reinterpret_cast<int*>(&n), 8, 140 const_cast<uint8*>(src), 8); 141 if (rv != SECSuccess) 142 goto done; 143 144 // TODO(wtc): Should this be PK11_Finalize? 145 rv = PK11_DigestFinal(ctxt, hash+8, &n, 0); 146 if (rv != SECSuccess) 147 goto done; 148 149 done: 150 if (ctxt) 151 PK11_DestroyContext(ctxt, PR_TRUE); 152 if (symkey) 153 PK11_FreeSymKey(symkey); 154 if (param) 155 SECITEM_FreeItem(param, PR_TRUE); 156 if (slot) 157 PK11_FreeSlot(slot); 158} 159 160#elif defined(OS_MACOSX) 161 162void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 163 CCCryptorStatus status; 164 size_t data_out_moved = 0; 165 status = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, 166 key, 8, NULL, src, 8, hash, 8, &data_out_moved); 167 DCHECK(status == kCCSuccess); 168 DCHECK(data_out_moved == 8); 169} 170 171#elif defined(OS_WIN) 172 173void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 174 crypto::ScopedHCRYPTPROV provider; 175 if (!CryptAcquireContext(provider.receive(), NULL, NULL, PROV_RSA_FULL, 176 CRYPT_VERIFYCONTEXT)) 177 return; 178 179 { 180 // Import the DES key. 181 struct KeyBlob { 182 BLOBHEADER header; 183 DWORD key_size; 184 BYTE key_data[8]; 185 }; 186 KeyBlob key_blob; 187 key_blob.header.bType = PLAINTEXTKEYBLOB; 188 key_blob.header.bVersion = CUR_BLOB_VERSION; 189 key_blob.header.reserved = 0; 190 key_blob.header.aiKeyAlg = CALG_DES; 191 key_blob.key_size = 8; // 64 bits 192 memcpy(key_blob.key_data, key, 8); 193 194 crypto::ScopedHCRYPTKEY key; 195 BOOL import_ok = CryptImportKey(provider, 196 reinterpret_cast<BYTE*>(&key_blob), 197 sizeof key_blob, 0, 0, key.receive()); 198 // Destroy the copy of the key. 199 SecureZeroMemory(key_blob.key_data, sizeof key_blob.key_data); 200 if (!import_ok) 201 return; 202 203 // No initialization vector required. 204 DWORD cipher_mode = CRYPT_MODE_ECB; 205 if (!CryptSetKeyParam(key, KP_MODE, reinterpret_cast<BYTE*>(&cipher_mode), 206 0)) 207 return; 208 209 // CryptoAPI requires us to copy the plaintext to the output buffer first. 210 CopyMemory(hash, src, 8); 211 // Pass a 'Final' of FALSE, otherwise CryptEncrypt appends one additional 212 // block of padding to the data. 213 DWORD hash_len = 8; 214 CryptEncrypt(key, 0, FALSE, 0, hash, &hash_len, 8); 215 } 216} 217 218#endif 219 220} // namespace net 221