iPXE
Data Structures | Functions | Variables
mschapv2.c File Reference

MS-CHAPv2 authentication. More...

#include <stdio.h>
#include <string.h>
#include <byteswap.h>
#include <ipxe/md4.h>
#include <ipxe/sha1.h>
#include <ipxe/des.h>
#include <ipxe/mschapv2.h>

Go to the source code of this file.

Data Structures

union  mschapv2_context
 MS-CHAPv2 context block. More...
 
union  mschapv2_challenge_hash
 MS-CHAPv2 challenge hash. More...
 
union  mschapv2_password_hash
 MS-CHAPv2 password hash. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static void mschapv2_challenge_hash (union mschapv2_context *ctx, const struct mschapv2_challenge *challenge, const struct mschapv2_challenge *peer, const char *username, union mschapv2_challenge_hash *chash)
 Calculate MS-CHAPv2 challenge hash. More...
 
static void mschapv2_password_hash (union mschapv2_context *ctx, const char *password, union mschapv2_password_hash *phash)
 Calculate MS-CHAPv2 password hash. More...
 
static void mschapv2_hash_hash (union mschapv2_context *ctx, union mschapv2_password_hash *phash)
 Hash the MS-CHAPv2 password hash. More...
 
static void mschapv2_expand_hash (union mschapv2_context *ctx, union mschapv2_password_hash *phash)
 Expand MS-CHAPv2 password hash by inserting DES dummy parity bits. More...
 
static void mschapv2_challenge_response (union mschapv2_context *ctx, const union mschapv2_challenge_hash *chash, const union mschapv2_password_hash *phash, struct mschapv2_nt_response *nt)
 Calculate MS-CHAPv2 challenge response. More...
 
void mschapv2_response (const char *username, const char *password, const struct mschapv2_challenge *challenge, const struct mschapv2_challenge *peer, struct mschapv2_response *response)
 Calculate MS-CHAPv2 challenge response. More...
 
void mschapv2_auth (const char *username, const char *password, const struct mschapv2_challenge *challenge, const struct mschapv2_response *response, struct mschapv2_auth *auth)
 Calculate MS-CHAPv2 authenticator response. More...
 

Variables

static const char mschapv2_magic1 [39]
 MS-CHAPv2 magic constant 1. More...
 
static const char mschapv2_magic2 [41]
 MS-CHAPv2 magic constant 2. More...
 

Detailed Description

MS-CHAPv2 authentication.

The algorithms used for MS-CHAPv2 authentication are defined in RFC 2759 section 8.

Definition in file mschapv2.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ mschapv2_challenge_hash()

static void mschapv2_challenge_hash ( union mschapv2_context ctx,
const struct mschapv2_challenge challenge,
const struct mschapv2_challenge peer,
const char *  username,
union mschapv2_challenge_hash chash 
)
static

Calculate MS-CHAPv2 challenge hash.

Parameters
ctxContext block
challengeAuthenticator challenge
peerPeer challenge
usernameUser name (or NULL to use empty string)
chashChallenge hash to fill in

This is the ChallengeHash() function as documented in RFC 2759 section 8.2.

Definition at line 119 of file mschapv2.c.

123  {
124  struct digest_algorithm *sha1 = &sha1_algorithm;
125 
126  /* Calculate SHA-1 hash of challenges and username */
127  digest_init ( sha1, ctx->sha1 );
128  digest_update ( sha1, ctx->sha1, peer, sizeof ( *peer ) );
129  digest_update ( sha1, ctx->sha1, challenge, sizeof ( *challenge ) );
130  if ( username ) {
131  digest_update ( sha1, ctx->sha1, username,
132  strlen ( username ) );
133  }
134  digest_final ( sha1, ctx->sha1, chash->sha1 );
135  DBGC ( ctx, "MSCHAPv2 authenticator challenge:\n" );
136  DBGC_HDA ( ctx, 0, challenge, sizeof ( *challenge ) );
137  DBGC ( ctx, "MSCHAPv2 peer challenge:\n" );
138  DBGC_HDA ( ctx, 0, peer, sizeof ( *peer ) );
139  DBGC ( ctx, "MSCHAPv2 challenge hash:\n" );
140  DBGC_HDA ( ctx, 0, chash->des, sizeof ( chash->des ) );
141 }
#define DBGC(...)
Definition: compiler.h:505
#define DBGC_HDA(...)
Definition: compiler.h:506
uint8_t des[DES_BLOCKSIZE]
DES plaintext block.
Definition: mschapv2.c:70
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
uint8_t sha1[SHA1_DIGEST_SIZE]
SHA-1 digest.
Definition: mschapv2.c:68
A message digest algorithm.
Definition: crypto.h:17
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
struct digest_algorithm sha1_algorithm
SHA-1 algorithm.
Definition: sha1.c:257

References ctx, DBGC, DBGC_HDA, mschapv2_challenge_hash::des, peer, mschapv2_challenge_hash::sha1, sha1_algorithm, and strlen().

Referenced by mschapv2_auth(), and mschapv2_response().

◆ mschapv2_password_hash()

static void mschapv2_password_hash ( union mschapv2_context ctx,
const char *  password,
union mschapv2_password_hash phash 
)
static

Calculate MS-CHAPv2 password hash.

Parameters
ctxContext block
passwordPassword (or NULL to use empty string)
phashPassword hash to fill in

This is the NtPasswordHash() function as documented in RFC 2759 section 8.3.

Definition at line 153 of file mschapv2.c.

155  {
156  struct digest_algorithm *md4 = &md4_algorithm;
157  uint16_t wc;
158  uint8_t c;
159 
160  /* Construct zero-padded MD4 hash of encoded password */
161  memset ( phash, 0, sizeof ( *phash ) );
162  digest_init ( md4, ctx->md4 );
163  if ( password ) {
164  while ( ( c = *(password++) ) ) {
165  wc = cpu_to_le16 ( c );
166  digest_update ( md4, ctx->md4, &wc, sizeof ( wc ) );
167  }
168  }
169  digest_final ( md4, ctx->md4, phash->md4 );
170  DBGC ( ctx, "MSCHAPv2 password hash:\n" );
171  DBGC_HDA ( ctx, 0, phash->md4, sizeof ( phash->md4 ) );
172 }
uint32_t c
Definition: md4.c:30
static wchar_t wc
Definition: wchar.h:22
unsigned short uint16_t
Definition: stdint.h:11
#define DBGC(...)
Definition: compiler.h:505
uint8_t md4[MD4_DIGEST_SIZE]
MD4 digest.
Definition: mschapv2.c:89
#define DBGC_HDA(...)
Definition: compiler.h:506
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
unsigned char uint8_t
Definition: stdint.h:10
#define cpu_to_le16(value)
Definition: byteswap.h:106
A message digest algorithm.
Definition: crypto.h:17
struct digest_algorithm md4_algorithm
MD4 algorithm.
Definition: md4.c:261
void * memset(void *dest, int character, size_t len) __nonnull

References c, cpu_to_le16, ctx, DBGC, DBGC_HDA, mschapv2_password_hash::md4, md4_algorithm, memset(), and wc.

Referenced by mschapv2_auth(), and mschapv2_response().

◆ mschapv2_hash_hash()

static void mschapv2_hash_hash ( union mschapv2_context ctx,
union mschapv2_password_hash phash 
)
static

Hash the MS-CHAPv2 password hash.

Parameters
ctxContext block
phashPassword hash to be rehashed

This is the HashNtPasswordHash() function as documented in RFC 2759 section 8.4.

Definition at line 183 of file mschapv2.c.

184  {
185  struct digest_algorithm *md4 = &md4_algorithm;
186 
187  /* Calculate MD4 hash of existing MD4 hash */
188  digest_init ( md4, ctx->md4 );
189  digest_update ( md4, ctx->md4, phash->md4, sizeof ( phash->md4 ) );
190  digest_final ( md4, ctx->md4, phash->md4 );
191  DBGC ( ctx, "MSCHAPv2 password hash hash:\n" );
192  DBGC_HDA ( ctx, 0, phash->md4, sizeof ( phash->md4 ) );
193 }
#define DBGC(...)
Definition: compiler.h:505
uint8_t md4[MD4_DIGEST_SIZE]
MD4 digest.
Definition: mschapv2.c:89
#define DBGC_HDA(...)
Definition: compiler.h:506
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
A message digest algorithm.
Definition: crypto.h:17
struct digest_algorithm md4_algorithm
MD4 algorithm.
Definition: md4.c:261

References ctx, DBGC, DBGC_HDA, mschapv2_password_hash::md4, and md4_algorithm.

Referenced by mschapv2_auth().

◆ mschapv2_expand_hash()

static void mschapv2_expand_hash ( union mschapv2_context ctx,
union mschapv2_password_hash phash 
)
static

Expand MS-CHAPv2 password hash by inserting DES dummy parity bits.

Parameters
ctxContext block
phashPassword hash to expand

This is part of the DesEncrypt() function as documented in RFC 2759 section 8.6.

Definition at line 204 of file mschapv2.c.

205  {
206  uint8_t *dst;
207  uint8_t *src;
208  unsigned int i;
209 
210  /* Expand password hash by inserting (unused) DES parity bits */
211  for ( i = ( sizeof ( phash->expand ) - 1 ) ; i > 0 ; i-- ) {
212  dst = &phash->expand[i];
213  src = ( dst - ( i / 8 ) );
214  *dst = ( ( ( src[-1] << 8 ) | src[0] ) >> ( i % 8 ) );
215  }
216  DBGC ( ctx, "MSCHAPv2 expanded password hash:\n" );
217  DBGC_HDA ( ctx, 0, phash->expand, sizeof ( phash->expand ) );
218 }
static void const void void * dst
Definition: crypto.h:244
static void const void * src
Definition: crypto.h:244
#define DBGC(...)
Definition: compiler.h:505
#define DBGC_HDA(...)
Definition: compiler.h:506
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
unsigned char uint8_t
Definition: stdint.h:10
uint8_t expand[3 *DES_BLOCKSIZE]
DES key expansion.
Definition: mschapv2.c:95

References ctx, DBGC, DBGC_HDA, dst, mschapv2_password_hash::expand, and src.

Referenced by mschapv2_response().

◆ mschapv2_challenge_response()

static void mschapv2_challenge_response ( union mschapv2_context ctx,
const union mschapv2_challenge_hash chash,
const union mschapv2_password_hash phash,
struct mschapv2_nt_response nt 
)
static

Calculate MS-CHAPv2 challenge response.

Parameters
ctxContext block
chashChallenge hash
phashPassword hash (after expansion)
ntNT response to fill in

This is the ChallengeResponse() function as documented in RFC 2759 section 8.5.

Definition at line 232 of file mschapv2.c.

235  {
236  struct cipher_algorithm *des = &des_algorithm;
237  unsigned int i;
238  int rc;
239 
240  /* Construct response. The design of the algorithm here is
241  * interesting, suggesting that an intern at Microsoft had
242  * heard the phrase "Triple DES" and hazarded a blind guess at
243  * what it might mean.
244  */
245  for ( i = 0 ; i < ( sizeof ( phash->des ) /
246  sizeof ( phash->des[0] ) ) ; i++ ) {
247  rc = cipher_setkey ( des, ctx->des, phash->des[i],
248  sizeof ( phash->des[i] ) );
249  assert ( rc == 0 ); /* no failure mode exists */
250  cipher_encrypt ( des, ctx->des, chash->des, nt->block[i],
251  sizeof ( chash->des ) );
252  }
253  DBGC ( ctx, "MSCHAPv2 NT response:\n" );
254  DBGC_HDA ( ctx, 0, nt, sizeof ( *nt ) );
255 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint8_t des[3][DES_BLOCKSIZE]
DES keys.
Definition: mschapv2.c:93
#define DBGC(...)
Definition: compiler.h:505
struct cipher_algorithm des_algorithm
Basic DES algorithm.
Definition: des.c:676
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:248
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define DBGC_HDA(...)
Definition: compiler.h:506
uint8_t des[DES_BLOCKSIZE]
DES plaintext block.
Definition: mschapv2.c:70
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
A cipher algorithm.
Definition: crypto.h:49
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:23
struct mschapv2_nt_response nt
NT response.
Definition: mschapv2.h:16

References assert(), mschapv2_nt_response::block, cipher_encrypt, ctx, DBGC, DBGC_HDA, mschapv2_challenge_hash::des, mschapv2_password_hash::des, des_algorithm, nt, and rc.

Referenced by mschapv2_response().

◆ mschapv2_response()

void mschapv2_response ( const char *  username,
const char *  password,
const struct mschapv2_challenge challenge,
const struct mschapv2_challenge peer,
struct mschapv2_response response 
)

Calculate MS-CHAPv2 challenge response.

Parameters
usernameUser name (or NULL to use empty string)
passwordPassword (or NULL to use empty string)
challengeAuthenticator challenge
peerPeer challenge
responseChallenge response to fill in

This is essentially the GenerateNTResponse() function as documented in RFC 2759 section 8.1.

Definition at line 269 of file mschapv2.c.

272  {
273  union mschapv2_context ctx;
274  union mschapv2_challenge_hash chash;
275  union mschapv2_password_hash phash;
276 
277  /* Zero reserved fields */
278  memset ( response, 0, sizeof ( *response ) );
279 
280  /* Copy peer challenge to response */
281  memcpy ( &response->peer, peer, sizeof ( response->peer ) );
282 
283  /* Construct challenge hash */
284  mschapv2_challenge_hash ( &ctx, challenge, peer, username, &chash );
285 
286  /* Construct expanded password hash */
287  mschapv2_password_hash ( &ctx, password, &phash );
288  mschapv2_expand_hash ( &ctx, &phash );
289 
290  /* Construct NT response */
291  mschapv2_challenge_response ( &ctx, &chash, &phash, &response->nt );
292  DBGC ( &ctx, "MSCHAPv2 challenge response:\n" );
293  DBGC_HDA ( &ctx, 0, response, sizeof ( *response ) );
294 }
MS-CHAPv2 context block.
Definition: mschapv2.c:50
MS-CHAPv2 password hash.
Definition: mschapv2.c:87
MS-CHAPv2 challenge hash.
Definition: mschapv2.c:66
#define DBGC(...)
Definition: compiler.h:505
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct mschapv2_nt_response nt
NT response.
Definition: mschapv2.h:33
static void mschapv2_challenge_response(union mschapv2_context *ctx, const union mschapv2_challenge_hash *chash, const union mschapv2_password_hash *phash, struct mschapv2_nt_response *nt)
Calculate MS-CHAPv2 challenge response.
Definition: mschapv2.c:232
static void mschapv2_challenge_hash(union mschapv2_context *ctx, const struct mschapv2_challenge *challenge, const struct mschapv2_challenge *peer, const char *username, union mschapv2_challenge_hash *chash)
Calculate MS-CHAPv2 challenge hash.
Definition: mschapv2.c:119
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:29
static void mschapv2_password_hash(union mschapv2_context *ctx, const char *password, union mschapv2_password_hash *phash)
Calculate MS-CHAPv2 password hash.
Definition: mschapv2.c:153
static void mschapv2_expand_hash(union mschapv2_context *ctx, union mschapv2_password_hash *phash)
Expand MS-CHAPv2 password hash by inserting DES dummy parity bits.
Definition: mschapv2.c:204
void * memset(void *dest, int character, size_t len) __nonnull

References ctx, DBGC, DBGC_HDA, memcpy(), memset(), mschapv2_challenge_hash(), mschapv2_challenge_response(), mschapv2_expand_hash(), mschapv2_password_hash(), mschapv2_response::nt, mschapv2_response::peer, and peer.

Referenced by eap_rx_mschapv2_request(), and mschapv2_okx().

◆ mschapv2_auth()

void mschapv2_auth ( const char *  username,
const char *  password,
const struct mschapv2_challenge challenge,
const struct mschapv2_response response,
struct mschapv2_auth auth 
)

Calculate MS-CHAPv2 authenticator response.

Parameters
usernameUser name (or NULL to use empty string)
passwordPassword (or NULL to use empty string)
challengeAuthenticator challenge
responseChallenge response
authAuthenticator response to fill in

This is essentially the GenerateAuthenticatorResponse() function as documented in RFC 2759 section 8.7.

Definition at line 308 of file mschapv2.c.

311  {
312  struct digest_algorithm *sha1 = &sha1_algorithm;
313  union mschapv2_context ctx;
314  union mschapv2_challenge_hash chash;
315  union mschapv2_password_hash phash;
316  char tmp[3];
317  char *wtf;
318  unsigned int i;
319 
320  /* Construct hash of password hash */
321  mschapv2_password_hash ( &ctx, password, &phash );
322  mschapv2_hash_hash ( &ctx, &phash );
323 
324  /* Construct unnamed intermediate hash */
325  digest_init ( sha1, ctx.sha1 );
326  digest_update ( sha1, ctx.sha1, phash.md4, sizeof ( phash.md4 ) );
327  digest_update ( sha1, ctx.sha1, &response->nt,
328  sizeof ( response->nt ) );
329  digest_update ( sha1, ctx.sha1, mschapv2_magic1,
330  sizeof ( mschapv2_magic1 ) );
331  digest_final ( sha1, ctx.sha1, phash.sha1 );
332  DBGC ( &ctx, "MSCHAPv2 NT response:\n" );
333  DBGC_HDA ( &ctx, 0, &response->nt, sizeof ( response->nt ) );
334  DBGC ( &ctx, "MSCHAPv2 unnamed intermediate hash:\n" );
335  DBGC_HDA ( &ctx, 0, phash.sha1, sizeof ( phash.sha1 ) );
336 
337  /* Construct challenge hash */
338  mschapv2_challenge_hash ( &ctx, challenge, &response->peer,
339  username, &chash );
340 
341  /* Construct authenticator response hash */
342  digest_init ( sha1, ctx.sha1 );
343  digest_update ( sha1, ctx.sha1, phash.sha1, sizeof ( phash.sha1 ) );
344  digest_update ( sha1, ctx.sha1, chash.des, sizeof ( chash.des ) );
345  digest_update ( sha1, ctx.sha1, mschapv2_magic2,
346  sizeof ( mschapv2_magic2 ) );
347  digest_final ( sha1, ctx.sha1, phash.sha1 );
348  DBGC ( &ctx, "MSCHAPv2 authenticator response hash:\n" );
349  DBGC_HDA ( &ctx, 0, phash.sha1, sizeof ( phash.sha1 ) );
350 
351  /* Encode authenticator response hash */
352  wtf = auth->wtf;
353  *(wtf++) = 'S';
354  *(wtf++) = '=';
355  DBGC ( &ctx, "MSCHAPv2 authenticator response: S=" );
356  for ( i = 0 ; i < sizeof ( phash.sha1 ) ; i++ ) {
357  snprintf ( tmp, sizeof ( tmp ), "%02X", phash.sha1[i] );
358  *(wtf++) = tmp[0];
359  *(wtf++) = tmp[1];
360  DBGC ( &ctx, "%s", tmp );
361  }
362  DBGC ( &ctx, "\n" );
363 }
MS-CHAPv2 context block.
Definition: mschapv2.c:50
static const char mschapv2_magic1[39]
MS-CHAPv2 magic constant 1.
Definition: mschapv2.c:99
MS-CHAPv2 password hash.
Definition: mschapv2.c:87
static void mschapv2_hash_hash(union mschapv2_context *ctx, union mschapv2_password_hash *phash)
Hash the MS-CHAPv2 password hash.
Definition: mschapv2.c:183
MS-CHAPv2 challenge hash.
Definition: mschapv2.c:66
#define DBGC(...)
Definition: compiler.h:505
uint8_t sha1[SHA1_DIGEST_SIZE]
SHA-1 digest.
Definition: mschapv2.c:91
static void void * auth
Definition: crypto.h:264
unsigned long tmp
Definition: linux_pci.h:53
char wtf[42]
Authenticator response string.
Definition: mschapv2.h:18
#define DBGC_HDA(...)
Definition: compiler.h:506
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct mschapv2_nt_response nt
NT response.
Definition: mschapv2.h:33
static void mschapv2_challenge_hash(union mschapv2_context *ctx, const struct mschapv2_challenge *challenge, const struct mschapv2_challenge *peer, const char *username, union mschapv2_challenge_hash *chash)
Calculate MS-CHAPv2 challenge hash.
Definition: mschapv2.c:119
static const char mschapv2_magic2[41]
MS-CHAPv2 magic constant 2.
Definition: mschapv2.c:103
A message digest algorithm.
Definition: crypto.h:17
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:29
static void mschapv2_password_hash(union mschapv2_context *ctx, const char *password, union mschapv2_password_hash *phash)
Calculate MS-CHAPv2 password hash.
Definition: mschapv2.c:153
struct digest_algorithm sha1_algorithm
SHA-1 algorithm.
Definition: sha1.c:257

References auth, ctx, DBGC, DBGC_HDA, mschapv2_challenge_hash::des, mschapv2_password_hash::md4, mschapv2_challenge_hash(), mschapv2_hash_hash(), mschapv2_magic1, mschapv2_magic2, mschapv2_password_hash(), mschapv2_response::nt, mschapv2_response::peer, mschapv2_password_hash::sha1, sha1_algorithm, snprintf(), tmp, and wtf.

Referenced by mschapv2_okx().

Variable Documentation

◆ mschapv2_magic1

const char mschapv2_magic1[39]
static
Initial value:
=
"Magic server to client signing constant"

MS-CHAPv2 magic constant 1.

Definition at line 99 of file mschapv2.c.

Referenced by mschapv2_auth().

◆ mschapv2_magic2

const char mschapv2_magic2[41]
static
Initial value:
=
"Pad to make it do more than one iteration"

MS-CHAPv2 magic constant 2.

Definition at line 103 of file mschapv2.c.

Referenced by mschapv2_auth().