1 /* $NetBSD: apop.c,v 1.1.1.2 2014/04/24 12:45:51 pettai Exp $ */
4 * Copyright (c) 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <sys/types.h>
41 #include <CommonCrypto/CommonDigest.h>
42 #include <CommonCrypto/CommonHMAC.h>
43 #include <krb5/roken.h>
45 #include "heim-auth.h"
46 #include <krb5/ntlm_err.h>
49 heim_generate_challenge(const char *hostname
)
51 char host
[MAXHOSTNAMELEN
], *str
= NULL
;
54 if (hostname
== NULL
) {
55 if (gethostname(host
, sizeof(host
)))
63 asprintf(&str
, "<%lu%lu@%s>", (unsigned long)t
,
64 (unsigned long)num
, hostname
);
70 heim_apop_create(const char *challenge
, const char *password
)
73 uint8_t hash
[CC_MD5_DIGEST_LENGTH
];
77 CC_MD5_Update(&ctx
, challenge
, strlen(challenge
));
78 CC_MD5_Update(&ctx
, password
, strlen(password
));
80 CC_MD5_Final(hash
, &ctx
);
82 hex_encode(hash
, sizeof(hash
), &str
);
90 heim_apop_verify(const char *challenge
, const char *password
, const char *response
)
95 str
= heim_apop_create(challenge
, password
);
99 res
= (strcasecmp(str
, response
) != 0);
103 return HNTLM_ERR_INVALID_APOP
;
107 struct heim_cram_md5
{
114 heim_cram_md5_export(const char *password
, heim_CRAM_MD5_STATE
*state
)
116 size_t keylen
= strlen(password
);
117 uint8_t key
[CC_MD5_BLOCK_BYTES
];
118 uint8_t pad
[CC_MD5_BLOCK_BYTES
];
119 struct heim_cram_md5 ctx
;
122 memset(&ctx
, 0, sizeof(ctx
));
124 if (keylen
> CC_MD5_BLOCK_BYTES
) {
125 CC_MD5(password
, keylen
, key
);
126 keylen
= sizeof(keylen
);
128 memcpy(key
, password
, keylen
);
131 memset(pad
, 0x36, sizeof(pad
));
132 for (n
= 0; n
< keylen
; n
++)
135 CC_MD5_Init(&ctx
.ipad
);
136 CC_MD5_Init(&ctx
.opad
);
138 CC_MD5_Update(&ctx
.ipad
, pad
, sizeof(pad
));
140 memset(pad
, 0x5c, sizeof(pad
));
141 for (n
= 0; n
< keylen
; n
++)
144 CC_MD5_Update(&ctx
.opad
, pad
, sizeof(pad
));
146 memset(pad
, 0, sizeof(pad
));
147 memset(key
, 0, sizeof(key
));
149 state
->istate
[0] = htonl(ctx
.ipad
.A
);
150 state
->istate
[1] = htonl(ctx
.ipad
.B
);
151 state
->istate
[2] = htonl(ctx
.ipad
.C
);
152 state
->istate
[3] = htonl(ctx
.ipad
.D
);
154 state
->ostate
[0] = htonl(ctx
.opad
.A
);
155 state
->ostate
[1] = htonl(ctx
.opad
.B
);
156 state
->ostate
[2] = htonl(ctx
.opad
.C
);
157 state
->ostate
[3] = htonl(ctx
.opad
.D
);
159 memset(&ctx
, 0, sizeof(ctx
));
164 heim_cram_md5_import(void *data
, size_t len
)
166 heim_CRAM_MD5_STATE state
;
170 if (len
!= sizeof(state
))
173 ctx
= calloc(1, sizeof(*ctx
));
177 memcpy(&state
, data
, sizeof(state
));
179 ctx
->ipad
.A
= ntohl(state
.istate
[0]);
180 ctx
->ipad
.B
= ntohl(state
.istate
[1]);
181 ctx
->ipad
.C
= ntohl(state
.istate
[2]);
182 ctx
->ipad
.D
= ntohl(state
.istate
[3]);
184 ctx
->opad
.A
= ntohl(state
.ostate
[0]);
185 ctx
->opad
.B
= ntohl(state
.ostate
[1]);
186 ctx
->opad
.C
= ntohl(state
.ostate
[2]);
187 ctx
->opad
.D
= ntohl(state
.ostate
[3]);
189 ctx
->ipad
.Nl
= ctx
->opad
.Nl
= 512;
190 ctx
->ipad
.Nh
= ctx
->opad
.Nh
= 0;
191 ctx
->ipad
.num
= ctx
->opad
.num
= 0;
197 heim_cram_md5_verify_ctx(heim_cram_md5 ctx
, const char *challenge
, const char *response
)
199 uint8_t hash
[CC_MD5_DIGEST_LENGTH
];
203 CC_MD5_Update(&ctx
->ipad
, challenge
, strlen(challenge
));
204 CC_MD5_Final(hash
, &ctx
->ipad
);
206 CC_MD5_Update(&ctx
->opad
, hash
, sizeof(hash
));
207 CC_MD5_Final(hash
, &ctx
->opad
);
209 hex_encode(hash
, sizeof(hash
), &str
);
213 res
= (strcasecmp(str
, response
) != 0);
217 return HNTLM_ERR_INVALID_CRAM_MD5
;
222 heim_cram_md5_free(heim_cram_md5 ctx
)
224 memset(ctx
, 0, sizeof(*ctx
));
230 heim_cram_md5_create(const char *challenge
, const char *password
)
233 uint8_t hash
[CC_MD5_DIGEST_LENGTH
];
236 CCHmacInit(&ctx
, kCCHmacAlgMD5
, password
, strlen(password
));
237 CCHmacUpdate(&ctx
, challenge
, strlen(challenge
));
238 CCHmacFinal(&ctx
, hash
);
240 memset(&ctx
, 0, sizeof(ctx
));
242 hex_encode(hash
, sizeof(hash
), &str
);
250 heim_cram_md5_verify(const char *challenge
, const char *password
, const char *response
)
255 str
= heim_cram_md5_create(challenge
, password
);
259 res
= (strcasecmp(str
, response
) != 0);
263 return HNTLM_ERR_INVALID_CRAM_MD5
;