2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
a partial implementation of DES designed for use in the
SMB authentication protocol
Copyright ( C ) Andrew Tridgell 1998
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2008-10-20 20:59:51 +04:00
# include "libcli/auth/libcli_auth.h"
2003-08-13 05:53:07 +04:00
2019-10-19 23:48:19 +03:00
# include <gnutls/gnutls.h>
# include <gnutls/crypto.h>
2004-05-29 12:11:46 +04:00
static void str_to_key ( const uint8_t * str , uint8_t * key )
2003-08-13 05:53:07 +04:00
{
int i ;
key [ 0 ] = str [ 0 ] > > 1 ;
key [ 1 ] = ( ( str [ 0 ] & 0x01 ) < < 6 ) | ( str [ 1 ] > > 2 ) ;
key [ 2 ] = ( ( str [ 1 ] & 0x03 ) < < 5 ) | ( str [ 2 ] > > 3 ) ;
key [ 3 ] = ( ( str [ 2 ] & 0x07 ) < < 4 ) | ( str [ 3 ] > > 4 ) ;
key [ 4 ] = ( ( str [ 3 ] & 0x0F ) < < 3 ) | ( str [ 4 ] > > 5 ) ;
key [ 5 ] = ( ( str [ 4 ] & 0x1F ) < < 2 ) | ( str [ 5 ] > > 6 ) ;
key [ 6 ] = ( ( str [ 5 ] & 0x3F ) < < 1 ) | ( str [ 6 ] > > 7 ) ;
key [ 7 ] = str [ 6 ] & 0x7F ;
for ( i = 0 ; i < 8 ; i + + ) {
key [ i ] = ( key [ i ] < < 1 ) ;
}
}
2019-10-19 23:48:19 +03:00
int des_crypt56_gnutls ( uint8_t out [ 8 ] , const uint8_t in [ 8 ] ,
const uint8_t key_in [ 7 ] ,
enum samba_gnutls_direction encrypt )
{
/*
* A single block DES - CBC op , with an all - zero IV is the same as DES
* because the IV is combined with the data using XOR .
* This allows us to use GNUTLS_CIPHER_DES_CBC from GnuTLS and not
* implement single - DES in Samba .
*
* In turn this is used to build DES - ECB , which is used
* for example in the NTLM challenge / response calculation .
*/
static const uint8_t iv8 [ 8 ] ;
gnutls_datum_t iv = { discard_const ( iv8 ) , 8 } ;
gnutls_datum_t key ;
gnutls_cipher_hd_t ctx ;
uint8_t key2 [ 8 ] ;
uint8_t outb [ 8 ] ;
int ret ;
memset ( out , 0 , 8 ) ;
str_to_key ( key_in , key2 ) ;
key . data = key2 ;
key . size = 8 ;
ret = gnutls_global_init ( ) ;
if ( ret ! = 0 ) {
return ret ;
}
ret = gnutls_cipher_init ( & ctx , GNUTLS_CIPHER_DES_CBC , & key , & iv ) ;
if ( ret ! = 0 ) {
return ret ;
}
memcpy ( outb , in , 8 ) ;
if ( encrypt = = SAMBA_GNUTLS_ENCRYPT ) {
ret = gnutls_cipher_encrypt ( ctx , outb , 8 ) ;
} else {
ret = gnutls_cipher_decrypt ( ctx , outb , 8 ) ;
}
if ( ret = = 0 ) {
memcpy ( out , outb , 8 ) ;
}
gnutls_cipher_deinit ( ctx ) ;
return ret ;
}
2019-11-07 18:16:26 +03:00
int E_P16 ( const uint8_t * p14 , uint8_t * p16 )
2003-08-13 05:53:07 +04:00
{
2004-06-01 14:12:52 +04:00
const uint8_t sp8 [ 8 ] = { 0x4b , 0x47 , 0x53 , 0x21 , 0x40 , 0x23 , 0x24 , 0x25 } ;
2019-11-07 18:16:26 +03:00
int ret ;
ret = des_crypt56_gnutls ( p16 , sp8 , p14 , SAMBA_GNUTLS_ENCRYPT ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( p16 + 8 , sp8 , p14 + 7 , SAMBA_GNUTLS_ENCRYPT ) ;
2003-08-13 05:53:07 +04:00
}
2019-11-08 17:40:01 +03:00
int E_P24 ( const uint8_t * p21 , const uint8_t * c8 , uint8_t * p24 )
2003-08-13 05:53:07 +04:00
{
2019-11-08 17:40:01 +03:00
int ret ;
ret = des_crypt56_gnutls ( p24 , c8 , p21 , SAMBA_GNUTLS_ENCRYPT ) ;
if ( ret ! = 0 ) {
return ret ;
}
ret = des_crypt56_gnutls ( p24 + 8 , c8 , p21 + 7 , SAMBA_GNUTLS_ENCRYPT ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( p24 + 16 , c8 , p21 + 14 , SAMBA_GNUTLS_ENCRYPT ) ;
2003-08-13 05:53:07 +04:00
}
2019-11-20 17:28:39 +03:00
int E_old_pw_hash ( uint8_t * p14 , const uint8_t * in , uint8_t * out )
2003-08-13 05:53:07 +04:00
{
2019-11-20 17:28:39 +03:00
int ret ;
ret = des_crypt56_gnutls ( out , in , p14 , SAMBA_GNUTLS_ENCRYPT ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( out + 8 , in + 8 , p14 + 7 , SAMBA_GNUTLS_ENCRYPT ) ;
2003-08-13 05:53:07 +04:00
}
2004-06-04 03:15:16 +04:00
/* des encryption with a 128 bit key */
2019-11-08 19:49:48 +03:00
int des_crypt128 ( uint8_t out [ 8 ] , const uint8_t in [ 8 ] , const uint8_t key [ 16 ] )
2003-08-13 05:53:07 +04:00
{
2004-05-29 12:11:46 +04:00
uint8_t buf [ 8 ] ;
2019-11-08 19:49:48 +03:00
int ret ;
ret = des_crypt56_gnutls ( buf , in , key , SAMBA_GNUTLS_ENCRYPT ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( out , buf , key + 9 , SAMBA_GNUTLS_ENCRYPT ) ;
2003-08-13 05:53:07 +04:00
}
2004-06-04 03:15:16 +04:00
/* des encryption with a 112 bit (14 byte) key */
2019-11-20 17:41:02 +03:00
int des_crypt112 ( uint8_t out [ 8 ] , const uint8_t in [ 8 ] , const uint8_t key [ 14 ] ,
enum samba_gnutls_direction encrypt )
2003-08-13 05:53:07 +04:00
{
2004-06-04 03:15:16 +04:00
uint8_t buf [ 8 ] ;
2019-11-20 17:41:02 +03:00
int ret ;
if ( encrypt = = SAMBA_GNUTLS_ENCRYPT ) {
ret = des_crypt56_gnutls ( buf , in , key , SAMBA_GNUTLS_ENCRYPT ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( out , buf , key + 7 , SAMBA_GNUTLS_ENCRYPT ) ;
2019-11-19 21:49:09 +03:00
}
2019-11-20 17:41:02 +03:00
ret = des_crypt56_gnutls ( buf , in , key + 7 , SAMBA_GNUTLS_DECRYPT ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( out , buf , key , SAMBA_GNUTLS_DECRYPT ) ;
2003-08-13 05:53:07 +04:00
}
2004-06-04 03:15:16 +04:00
/* des encryption of a 16 byte lump of data with a 112 bit key */
2019-11-20 18:02:16 +03:00
int des_crypt112_16 ( uint8_t out [ 16 ] , const uint8_t in [ 16 ] , const uint8_t key [ 14 ] ,
enum samba_gnutls_direction encrypt )
2004-06-04 03:15:16 +04:00
{
2019-11-20 18:02:16 +03:00
int ret ;
ret = des_crypt56_gnutls ( out , in , key , encrypt ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( out + 8 , in + 8 , key + 7 , encrypt ) ;
2004-06-04 03:15:16 +04:00
}
2004-04-21 09:01:31 +04:00
2003-08-13 05:53:07 +04:00
/* Decode a sam password hash into a password. The password hash is the
same method used to store passwords in the NT registry . The DES key
used is based on the RID of the user . */
2019-11-07 20:40:03 +03:00
int sam_rid_crypt ( unsigned int rid , const uint8_t * in , uint8_t * out ,
enum samba_gnutls_direction encrypt )
2003-08-13 05:53:07 +04:00
{
2004-06-01 12:30:34 +04:00
uint8_t s [ 14 ] ;
2019-11-07 20:40:03 +03:00
int ret ;
2003-08-13 05:53:07 +04:00
2004-06-01 12:30:34 +04:00
s [ 0 ] = s [ 4 ] = s [ 8 ] = s [ 12 ] = ( uint8_t ) ( rid & 0xFF ) ;
s [ 1 ] = s [ 5 ] = s [ 9 ] = s [ 13 ] = ( uint8_t ) ( ( rid > > 8 ) & 0xFF ) ;
s [ 2 ] = s [ 6 ] = s [ 10 ] = ( uint8_t ) ( ( rid > > 16 ) & 0xFF ) ;
s [ 3 ] = s [ 7 ] = s [ 11 ] = ( uint8_t ) ( ( rid > > 24 ) & 0xFF ) ;
2003-08-13 05:53:07 +04:00
2019-11-07 20:40:03 +03:00
ret = des_crypt56_gnutls ( out , in , s , encrypt ) ;
if ( ret ! = 0 ) {
return ret ;
}
return des_crypt56_gnutls ( out + 8 , in + 8 , s + 7 , encrypt ) ;
2003-08-13 05:53:07 +04:00
}