1*613a2f6bSGordon Ross /* 2*613a2f6bSGordon Ross * CDDL HEADER START 3*613a2f6bSGordon Ross * 4*613a2f6bSGordon Ross * The contents of this file are subject to the terms of the 5*613a2f6bSGordon Ross * Common Development and Distribution License (the "License"). 6*613a2f6bSGordon Ross * You may not use this file except in compliance with the License. 7*613a2f6bSGordon Ross * 8*613a2f6bSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*613a2f6bSGordon Ross * or http://www.opensolaris.org/os/licensing. 10*613a2f6bSGordon Ross * See the License for the specific language governing permissions 11*613a2f6bSGordon Ross * and limitations under the License. 12*613a2f6bSGordon Ross * 13*613a2f6bSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14*613a2f6bSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*613a2f6bSGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16*613a2f6bSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17*613a2f6bSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18*613a2f6bSGordon Ross * 19*613a2f6bSGordon Ross * CDDL HEADER END 20*613a2f6bSGordon Ross */ 21*613a2f6bSGordon Ross 22*613a2f6bSGordon Ross /* 23*613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*613a2f6bSGordon Ross * Use is subject to license terms. 25*613a2f6bSGordon Ross */ 26*613a2f6bSGordon Ross 27*613a2f6bSGordon Ross /* 28*613a2f6bSGordon Ross * Crypto support, using libpkcs11 29*613a2f6bSGordon Ross * 30*613a2f6bSGordon Ross * Some code copied from the server: libsmb smb_crypt.c 31*613a2f6bSGordon Ross * with minor changes, i.e. errno.h return values. 32*613a2f6bSGordon Ross * XXX: Move this to a common library (later). 33*613a2f6bSGordon Ross */ 34*613a2f6bSGordon Ross 35*613a2f6bSGordon Ross #include <sys/types.h> 36*613a2f6bSGordon Ross #include <sys/md4.h> 37*613a2f6bSGordon Ross 38*613a2f6bSGordon Ross #include <errno.h> 39*613a2f6bSGordon Ross #include <fcntl.h> 40*613a2f6bSGordon Ross #include <string.h> 41*613a2f6bSGordon Ross 42*613a2f6bSGordon Ross #include <security/cryptoki.h> 43*613a2f6bSGordon Ross #include <security/pkcs11.h> 44*613a2f6bSGordon Ross #include <cryptoutil.h> 45*613a2f6bSGordon Ross 46*613a2f6bSGordon Ross #include "smb_crypt.h" 47*613a2f6bSGordon Ross 48*613a2f6bSGordon Ross static void 49*613a2f6bSGordon Ross smb_initlmkey(uchar_t *keyout, const uchar_t *keyin); 50*613a2f6bSGordon Ross 51*613a2f6bSGordon Ross /* 52*613a2f6bSGordon Ross * Like libsmb smb_auth_DES, 53*613a2f6bSGordon Ross * but use uchar_t, return errno. 54*613a2f6bSGordon Ross */ 55*613a2f6bSGordon Ross int 56*613a2f6bSGordon Ross smb_encrypt_DES(uchar_t *Result, int ResultLen, 57*613a2f6bSGordon Ross const uchar_t *Key, int KeyLen, 58*613a2f6bSGordon Ross const uchar_t *Data, int DataLen) 59*613a2f6bSGordon Ross { 60*613a2f6bSGordon Ross CK_RV rv; 61*613a2f6bSGordon Ross CK_MECHANISM mechanism; 62*613a2f6bSGordon Ross CK_OBJECT_HANDLE hKey; 63*613a2f6bSGordon Ross CK_SESSION_HANDLE hSession; 64*613a2f6bSGordon Ross CK_ULONG ciphertext_len; 65*613a2f6bSGordon Ross uchar_t des_key[8]; 66*613a2f6bSGordon Ross int error = 0; 67*613a2f6bSGordon Ross int K, D; 68*613a2f6bSGordon Ross int k, d; 69*613a2f6bSGordon Ross 70*613a2f6bSGordon Ross /* Calculate proper number of iterations */ 71*613a2f6bSGordon Ross K = KeyLen / 7; 72*613a2f6bSGordon Ross D = DataLen / 8; 73*613a2f6bSGordon Ross 74*613a2f6bSGordon Ross if (ResultLen < (K * 8 * D)) { 75*613a2f6bSGordon Ross return (EINVAL); 76*613a2f6bSGordon Ross } 77*613a2f6bSGordon Ross 78*613a2f6bSGordon Ross /* 79*613a2f6bSGordon Ross * Use SUNW convenience function to initialize the cryptoki 80*613a2f6bSGordon Ross * library, and open a session with a slot that supports 81*613a2f6bSGordon Ross * the mechanism we plan on using. 82*613a2f6bSGordon Ross */ 83*613a2f6bSGordon Ross mechanism.mechanism = CKM_DES_ECB; 84*613a2f6bSGordon Ross mechanism.pParameter = NULL; 85*613a2f6bSGordon Ross mechanism.ulParameterLen = 0; 86*613a2f6bSGordon Ross rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession); 87*613a2f6bSGordon Ross if (rv != CKR_OK) { 88*613a2f6bSGordon Ross return (ENOTSUP); 89*613a2f6bSGordon Ross } 90*613a2f6bSGordon Ross 91*613a2f6bSGordon Ross for (k = 0; k < K; k++) { 92*613a2f6bSGordon Ross smb_initlmkey(des_key, &Key[k * 7]); 93*613a2f6bSGordon Ross rv = SUNW_C_KeyToObject(hSession, mechanism.mechanism, 94*613a2f6bSGordon Ross des_key, 8, &hKey); 95*613a2f6bSGordon Ross if (rv != CKR_OK) { 96*613a2f6bSGordon Ross error = EIO; 97*613a2f6bSGordon Ross goto exit_session; 98*613a2f6bSGordon Ross } 99*613a2f6bSGordon Ross /* Initialize the encryption operation in the session */ 100*613a2f6bSGordon Ross rv = C_EncryptInit(hSession, &mechanism, hKey); 101*613a2f6bSGordon Ross if (rv != CKR_OK) { 102*613a2f6bSGordon Ross error = EIO; 103*613a2f6bSGordon Ross goto exit_encrypt; 104*613a2f6bSGordon Ross } 105*613a2f6bSGordon Ross ciphertext_len = DataLen; 106*613a2f6bSGordon Ross for (d = 0; d < D; d++) { 107*613a2f6bSGordon Ross /* Read in the data and encrypt this portion */ 108*613a2f6bSGordon Ross rv = C_EncryptUpdate(hSession, 109*613a2f6bSGordon Ross (CK_BYTE_PTR)Data + (d * 8), 8, 110*613a2f6bSGordon Ross &Result[(k * (8 * D)) + (d * 8)], 111*613a2f6bSGordon Ross &ciphertext_len); 112*613a2f6bSGordon Ross if (rv != CKR_OK) { 113*613a2f6bSGordon Ross error = EIO; 114*613a2f6bSGordon Ross goto exit_encrypt; 115*613a2f6bSGordon Ross } 116*613a2f6bSGordon Ross } 117*613a2f6bSGordon Ross (void) C_DestroyObject(hSession, hKey); 118*613a2f6bSGordon Ross } 119*613a2f6bSGordon Ross goto exit_session; 120*613a2f6bSGordon Ross 121*613a2f6bSGordon Ross exit_encrypt: 122*613a2f6bSGordon Ross (void) C_DestroyObject(hSession, hKey); 123*613a2f6bSGordon Ross exit_session: 124*613a2f6bSGordon Ross (void) C_CloseSession(hSession); 125*613a2f6bSGordon Ross 126*613a2f6bSGordon Ross return (error); 127*613a2f6bSGordon Ross } 128*613a2f6bSGordon Ross 129*613a2f6bSGordon Ross /* 130*613a2f6bSGordon Ross * See "Netlogon Credential Computation" section of MS-NRPC document. 131*613a2f6bSGordon Ross * Same as in libsmb, but output arg first. 132*613a2f6bSGordon Ross */ 133*613a2f6bSGordon Ross static void 134*613a2f6bSGordon Ross smb_initlmkey(uchar_t *keyout, const uchar_t *keyin) 135*613a2f6bSGordon Ross { 136*613a2f6bSGordon Ross int i; 137*613a2f6bSGordon Ross 138*613a2f6bSGordon Ross keyout[0] = keyin[0] >> 0x01; 139*613a2f6bSGordon Ross keyout[1] = ((keyin[0] & 0x01) << 6) | (keyin[1] >> 2); 140*613a2f6bSGordon Ross keyout[2] = ((keyin[1] & 0x03) << 5) | (keyin[2] >> 3); 141*613a2f6bSGordon Ross keyout[3] = ((keyin[2] & 0x07) << 4) | (keyin[3] >> 4); 142*613a2f6bSGordon Ross keyout[4] = ((keyin[3] & 0x0f) << 3) | (keyin[4] >> 5); 143*613a2f6bSGordon Ross keyout[5] = ((keyin[4] & 0x1f) << 2) | (keyin[5] >> 6); 144*613a2f6bSGordon Ross keyout[6] = ((keyin[5] & 0x3f) << 1) | (keyin[6] >> 7); 145*613a2f6bSGordon Ross keyout[7] = keyin[6] & 0x7f; 146*613a2f6bSGordon Ross 147*613a2f6bSGordon Ross for (i = 0; i < 8; i++) 148*613a2f6bSGordon Ross keyout[i] = (keyout[i] << 1) & 0xfe; 149*613a2f6bSGordon Ross } 150*613a2f6bSGordon Ross 151*613a2f6bSGordon Ross /* 152*613a2f6bSGordon Ross * Get some random bytes from /dev/urandom 153*613a2f6bSGordon Ross * 154*613a2f6bSGordon Ross * There may be a preferred way to call this via libpkcs11 155*613a2f6bSGordon Ross * XXX: (see: C_GenerateRandom, etc. -- later...) 156*613a2f6bSGordon Ross * Just read from /dev/urandom for now. 157*613a2f6bSGordon Ross */ 158*613a2f6bSGordon Ross int 159*613a2f6bSGordon Ross smb_get_urandom(void *data, size_t dlen) 160*613a2f6bSGordon Ross { 161*613a2f6bSGordon Ross int fd, rlen; 162*613a2f6bSGordon Ross 163*613a2f6bSGordon Ross fd = open("/dev/urandom", O_RDONLY); 164*613a2f6bSGordon Ross if (fd < 0) 165*613a2f6bSGordon Ross return (errno); 166*613a2f6bSGordon Ross 167*613a2f6bSGordon Ross rlen = read(fd, data, dlen); 168*613a2f6bSGordon Ross close(fd); 169*613a2f6bSGordon Ross 170*613a2f6bSGordon Ross if (rlen < 0) 171*613a2f6bSGordon Ross return (errno); 172*613a2f6bSGordon Ross if (rlen < dlen) 173*613a2f6bSGordon Ross return (EIO); 174*613a2f6bSGordon Ross return (0); 175*613a2f6bSGordon Ross } 176