iPXE
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)
 FILE_SECBOOT (PERMITTED)
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.
static void mschapv2_password_hash (union mschapv2_context *ctx, const char *password, union mschapv2_password_hash *phash)
 Calculate MS-CHAPv2 password hash.
static void mschapv2_hash_hash (union mschapv2_context *ctx, union mschapv2_password_hash *phash)
 Hash the MS-CHAPv2 password hash.
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.
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.
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.
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.

Variables

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

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 )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ mschapv2_challenge_hash()

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 120 of file mschapv2.c.

124 {
125 struct digest_algorithm *sha1 = &sha1_algorithm;
126
127 /* Calculate SHA-1 hash of challenges and username */
128 digest_init ( sha1, ctx->sha1 );
129 digest_update ( sha1, ctx->sha1, peer, sizeof ( *peer ) );
130 digest_update ( sha1, ctx->sha1, challenge, sizeof ( *challenge ) );
131 if ( username ) {
132 digest_update ( sha1, ctx->sha1, username,
133 strlen ( username ) );
134 }
135 digest_final ( sha1, ctx->sha1, chash->sha1 );
136 DBGC ( ctx, "MSCHAPv2 authenticator challenge:\n" );
137 DBGC_HDA ( ctx, 0, challenge, sizeof ( *challenge ) );
138 DBGC ( ctx, "MSCHAPv2 peer challenge:\n" );
139 DBGC_HDA ( ctx, 0, peer, sizeof ( *peer ) );
140 DBGC ( ctx, "MSCHAPv2 challenge hash:\n" );
141 DBGC_HDA ( ctx, 0, chash->des, sizeof ( chash->des ) );
142}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:219
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:230
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:224
static struct dynamic_item username
Definition login_ui.c:36
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:1
struct digest_algorithm sha1_algorithm
SHA-1 algorithm.
Definition sha1.c:258
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
A message digest algorithm.
Definition crypto.h:19
uint8_t sha1[SHA1_DIGEST_SIZE]
SHA-1 digest.
Definition mschapv2.c:69
uint8_t des[DES_BLOCKSIZE]
DES plaintext block.
Definition mschapv2.c:71

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

Referenced by mschapv2_auth(), and mschapv2_response().

◆ mschapv2_password_hash()

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 154 of file mschapv2.c.

156 {
157 struct digest_algorithm *md4 = &md4_algorithm;
158 uint16_t wc;
159 uint8_t c;
160
161 /* Construct zero-padded MD4 hash of encoded password */
162 memset ( phash, 0, sizeof ( *phash ) );
163 digest_init ( md4, ctx->md4 );
164 if ( password ) {
165 while ( ( c = *(password++) ) ) {
166 wc = cpu_to_le16 ( c );
167 digest_update ( md4, ctx->md4, &wc, sizeof ( wc ) );
168 }
169 }
170 digest_final ( md4, ctx->md4, phash->md4 );
171 DBGC ( ctx, "MSCHAPv2 password hash:\n" );
172 DBGC_HDA ( ctx, 0, phash->md4, sizeof ( phash->md4 ) );
173}
unsigned short uint16_t
Definition stdint.h:11
unsigned char uint8_t
Definition stdint.h:10
#define cpu_to_le16(value)
Definition byteswap.h:107
void * memset(void *dest, int character, size_t len) __nonnull
static struct dynamic_item password
Definition login_ui.c:37
struct digest_algorithm md4_algorithm
MD4 algorithm.
Definition md4.c:262
uint8_t md4[MD4_DIGEST_SIZE]
MD4 digest.
Definition mschapv2.c:90
static wchar_t wc
Definition wchar.h:23

References cpu_to_le16, ctx, DBGC, DBGC_HDA, digest_final(), digest_init(), digest_update(), mschapv2_password_hash::md4, md4_algorithm, memset(), password, and wc.

Referenced by mschapv2_auth(), and mschapv2_response().

◆ mschapv2_hash_hash()

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 184 of file mschapv2.c.

185 {
186 struct digest_algorithm *md4 = &md4_algorithm;
187
188 /* Calculate MD4 hash of existing MD4 hash */
189 digest_init ( md4, ctx->md4 );
190 digest_update ( md4, ctx->md4, phash->md4, sizeof ( phash->md4 ) );
191 digest_final ( md4, ctx->md4, phash->md4 );
192 DBGC ( ctx, "MSCHAPv2 password hash hash:\n" );
193 DBGC_HDA ( ctx, 0, phash->md4, sizeof ( phash->md4 ) );
194}

References ctx, DBGC, DBGC_HDA, digest_final(), digest_init(), digest_update(), mschapv2_password_hash::md4, and md4_algorithm.

Referenced by mschapv2_auth().

◆ mschapv2_expand_hash()

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 205 of file mschapv2.c.

206 {
207 uint8_t *dst;
208 uint8_t *src;
209 unsigned int i;
210
211 /* Expand password hash by inserting (unused) DES parity bits */
212 for ( i = ( sizeof ( phash->expand ) - 1 ) ; i > 0 ; i-- ) {
213 dst = &phash->expand[i];
214 src = ( dst - ( i / 8 ) );
215 *dst = ( ( ( src[-1] << 8 ) | src[0] ) >> ( i % 8 ) );
216 }
217 DBGC ( ctx, "MSCHAPv2 expanded password hash:\n" );
218 DBGC_HDA ( ctx, 0, phash->expand, sizeof ( phash->expand ) );
219}
static const void * src
Definition string.h:48
uint8_t expand[3 *DES_BLOCKSIZE]
DES key expansion.
Definition mschapv2.c:96

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

Referenced by mschapv2_response().

◆ mschapv2_challenge_response()

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 233 of file mschapv2.c.

236 {
237 struct cipher_algorithm *des = &des_algorithm;
238 unsigned int i;
239 int rc;
240
241 /* Construct response. The design of the algorithm here is
242 * interesting, suggesting that an intern at Microsoft had
243 * heard the phrase "Triple DES" and hazarded a blind guess at
244 * what it might mean.
245 */
246 for ( i = 0 ; i < ( sizeof ( phash->des ) /
247 sizeof ( phash->des[0] ) ) ; i++ ) {
248 rc = cipher_setkey ( des, ctx->des, phash->des[i],
249 sizeof ( phash->des[i] ) );
250 assert ( rc == 0 ); /* no failure mode exists */
251 cipher_encrypt ( des, ctx->des, chash->des, nt->block[i],
252 sizeof ( chash->des ) );
253 }
254 DBGC ( ctx, "MSCHAPv2 NT response:\n" );
255 DBGC_HDA ( ctx, 0, nt, sizeof ( *nt ) );
256}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
struct cipher_algorithm des_algorithm
Basic DES algorithm.
Definition des.c:678
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition crypto.h:235
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition crypto.h:251
struct mschapv2_nt_response nt
NT response.
Definition mschapv2.h:5
A cipher algorithm.
Definition crypto.h:51
uint8_t des[3][DES_BLOCKSIZE]
DES keys.
Definition mschapv2.c:94

References assert, cipher_encrypt, cipher_setkey(), 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 270 of file mschapv2.c.

273 {
274 union mschapv2_context ctx;
275 union mschapv2_challenge_hash chash;
276 union mschapv2_password_hash phash;
277
278 /* Zero reserved fields */
279 memset ( response, 0, sizeof ( *response ) );
280
281 /* Copy peer challenge to response */
282 memcpy ( &response->peer, peer, sizeof ( response->peer ) );
283
284 /* Construct challenge hash */
285 mschapv2_challenge_hash ( &ctx, challenge, peer, username, &chash );
286
287 /* Construct expanded password hash */
288 mschapv2_password_hash ( &ctx, password, &phash );
289 mschapv2_expand_hash ( &ctx, &phash );
290
291 /* Construct NT response */
292 mschapv2_challenge_response ( &ctx, &chash, &phash, &response->nt );
293 DBGC ( &ctx, "MSCHAPv2 challenge response:\n" );
294 DBGC_HDA ( &ctx, 0, response, sizeof ( *response ) );
295}
void * memcpy(void *dest, const void *src, size_t len) __nonnull
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:233
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:205
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:120
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:154
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:30
struct mschapv2_nt_response nt
NT response.
Definition mschapv2.h:34
MS-CHAPv2 challenge hash.
Definition mschapv2.c:67
MS-CHAPv2 context block.
Definition mschapv2.c:51
MS-CHAPv2 password hash.
Definition mschapv2.c:88

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

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 309 of file mschapv2.c.

312 {
313 struct digest_algorithm *sha1 = &sha1_algorithm;
314 union mschapv2_context ctx;
315 union mschapv2_challenge_hash chash;
316 union mschapv2_password_hash phash;
317 char tmp[3];
318 char *wtf;
319 unsigned int i;
320
321 /* Construct hash of password hash */
322 mschapv2_password_hash ( &ctx, password, &phash );
323 mschapv2_hash_hash ( &ctx, &phash );
324
325 /* Construct unnamed intermediate hash */
326 digest_init ( sha1, ctx.sha1 );
327 digest_update ( sha1, ctx.sha1, phash.md4, sizeof ( phash.md4 ) );
328 digest_update ( sha1, ctx.sha1, &response->nt,
329 sizeof ( response->nt ) );
331 sizeof ( mschapv2_magic1 ) );
332 digest_final ( sha1, ctx.sha1, phash.sha1 );
333 DBGC ( &ctx, "MSCHAPv2 NT response:\n" );
334 DBGC_HDA ( &ctx, 0, &response->nt, sizeof ( response->nt ) );
335 DBGC ( &ctx, "MSCHAPv2 unnamed intermediate hash:\n" );
336 DBGC_HDA ( &ctx, 0, phash.sha1, sizeof ( phash.sha1 ) );
337
338 /* Construct challenge hash */
339 mschapv2_challenge_hash ( &ctx, challenge, &response->peer,
340 username, &chash );
341
342 /* Construct authenticator response hash */
343 digest_init ( sha1, ctx.sha1 );
344 digest_update ( sha1, ctx.sha1, phash.sha1, sizeof ( phash.sha1 ) );
345 digest_update ( sha1, ctx.sha1, chash.des, sizeof ( chash.des ) );
347 sizeof ( mschapv2_magic2 ) );
348 digest_final ( sha1, ctx.sha1, phash.sha1 );
349 DBGC ( &ctx, "MSCHAPv2 authenticator response hash:\n" );
350 DBGC_HDA ( &ctx, 0, phash.sha1, sizeof ( phash.sha1 ) );
351
352 /* Encode authenticator response hash */
353 wtf = auth->wtf;
354 *(wtf++) = 'S';
355 *(wtf++) = '=';
356 DBGC ( &ctx, "MSCHAPv2 authenticator response: S=" );
357 for ( i = 0 ; i < sizeof ( phash.sha1 ) ; i++ ) {
358 snprintf ( tmp, sizeof ( tmp ), "%02X", phash.sha1[i] );
359 *(wtf++) = tmp[0];
360 *(wtf++) = tmp[1];
361 DBGC ( &ctx, "%s", tmp );
362 }
363 DBGC ( &ctx, "\n" );
364}
unsigned long tmp
Definition linux_pci.h:65
static void mschapv2_hash_hash(union mschapv2_context *ctx, union mschapv2_password_hash *phash)
Hash the MS-CHAPv2 password hash.
Definition mschapv2.c:184
static const char mschapv2_magic1[39]
MS-CHAPv2 magic constant 1.
Definition mschapv2.c:100
static const char mschapv2_magic2[41]
MS-CHAPv2 magic constant 2.
Definition mschapv2.c:104
char wtf[42]
Authenticator response string.
Definition mschapv2.h:7
char wtf[42]
Authenticator response string.
Definition mschapv2.h:48
uint8_t sha1[SHA1_DIGEST_SIZE]
SHA-1 digest.
Definition mschapv2.c:92
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References ctx, DBGC, DBGC_HDA, mschapv2_challenge_hash::des, digest_final(), digest_init(), digest_update(), mschapv2_password_hash::md4, mschapv2_challenge_hash(), mschapv2_hash_hash(), mschapv2_magic1, mschapv2_magic2, mschapv2_password_hash(), mschapv2_response::nt, password, mschapv2_response::peer, mschapv2_password_hash::sha1, sha1_algorithm, snprintf(), tmp, username, mschapv2_auth::wtf, 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 100 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 104 of file mschapv2.c.

Referenced by mschapv2_auth().