OpenVPN
httpdigest.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include "syshead.h"
29
30#if PROXY_DIGEST_AUTH
31
32#include "crypto.h"
33#include "httpdigest.h"
34
35static void
37 IN HASH Bin,
38 OUT HASHHEX Hex
39 )
40{
41 unsigned short i;
42 unsigned char j;
43
44 for (i = 0; i < HASHLEN; i++)
45 {
46 j = (Bin[i] >> 4) & 0xf;
47 if (j <= 9)
48 {
49 Hex[i*2] = (j + '0');
50 }
51 else
52 {
53 Hex[i*2] = (j + 'a' - 10);
54 }
55 j = Bin[i] & 0xf;
56 if (j <= 9)
57 {
58 Hex[i*2+1] = (j + '0');
59 }
60 else
61 {
62 Hex[i*2+1] = (j + 'a' - 10);
63 }
64 }
65 Hex[HASHHEXLEN] = '\0';
66}
67
68/* calculate H(A1) as per spec */
69void
71 IN char *pszAlg,
72 IN char *pszUserName,
73 IN char *pszRealm,
74 IN char *pszPassword,
75 IN char *pszNonce,
76 IN char *pszCNonce,
77 OUT HASHHEX SessionKey
78 )
79{
80 HASH HA1;
81 md_ctx_t *md5_ctx = md_ctx_new();
82
83 md_ctx_init(md5_ctx, "MD5");
84 md_ctx_update(md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName));
85 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
86 md_ctx_update(md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm));
87 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
88 md_ctx_update(md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword));
89 md_ctx_final(md5_ctx, HA1);
90 if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0)
91 {
92 md_ctx_init(md5_ctx, "MD5");
93 md_ctx_update(md5_ctx, HA1, HASHLEN);
94 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
95 md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
96 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
97 md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
98 md_ctx_final(md5_ctx, HA1);
99 }
100 md_ctx_cleanup(md5_ctx);
101 md_ctx_free(md5_ctx);
102 CvtHex(HA1, SessionKey);
103}
104
105/* calculate request-digest/response-digest as per HTTP Digest spec */
106void
108 IN HASHHEX HA1, /* H(A1) */
109 IN char *pszNonce, /* nonce from server */
110 IN char *pszNonceCount, /* 8 hex digits */
111 IN char *pszCNonce, /* client nonce */
112 IN char *pszQop, /* qop-value: "", "auth", "auth-int" */
113 IN char *pszMethod, /* method from the request */
114 IN char *pszDigestUri, /* requested URL */
115 IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
116 OUT HASHHEX Response /* request-digest or response-digest */
117 )
118{
119 HASH HA2;
120 HASH RespHash;
121 HASHHEX HA2Hex;
122
123 md_ctx_t *md5_ctx = md_ctx_new();
124
125 /* calculate H(A2) */
126 md_ctx_init(md5_ctx, "MD5");
127 md_ctx_update(md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod));
128 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
129 md_ctx_update(md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri));
130 if (strcasecmp(pszQop, "auth-int") == 0)
131 {
132 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
133 md_ctx_update(md5_ctx, HEntity, HASHHEXLEN);
134 }
135 md_ctx_final(md5_ctx, HA2);
136 CvtHex(HA2, HA2Hex);
137
138 /* calculate response */
139 md_ctx_init(md5_ctx, "MD5");
140 md_ctx_update(md5_ctx, HA1, HASHHEXLEN);
141 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
142 md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
143 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
144 if (*pszQop)
145 {
146 md_ctx_update(md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount));
147 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
148 md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
149 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
150 md_ctx_update(md5_ctx, (const uint8_t *) pszQop, strlen(pszQop));
151 md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
152 }
153 md_ctx_update(md5_ctx, HA2Hex, HASHHEXLEN);
154 md_ctx_final(md5_ctx, RespHash);
155 md_ctx_cleanup(md5_ctx);
156 md_ctx_free(md5_ctx);
157 CvtHex(RespHash, Response);
158}
159
160#endif /* if PROXY_DIGEST_AUTH */
Data Channel Cryptography Module.
md_ctx_t * md_ctx_new(void)
void md_ctx_update(md_ctx_t *ctx, const uint8_t *src, int src_len)
void md_ctx_cleanup(md_ctx_t *ctx)
void md_ctx_final(md_ctx_t *ctx, uint8_t *dst)
void md_ctx_init(md_ctx_t *ctx, const char *mdname)
Initialises the given message digest context.
void md_ctx_free(md_ctx_t *ctx)
mbedtls_md_context_t md_ctx_t
Generic message digest context.
void DigestCalcHA1(IN char *pszAlg, IN char *pszUserName, IN char *pszRealm, IN char *pszPassword, IN char *pszNonce, IN char *pszCNonce, OUT HASHHEX SessionKey)
Definition httpdigest.c:70
static void CvtHex(IN HASH Bin, OUT HASHHEX Hex)
Definition httpdigest.c:36
void DigestCalcResponse(IN HASHHEX HA1, IN char *pszNonce, IN char *pszNonceCount, IN char *pszCNonce, IN char *pszQop, IN char *pszMethod, IN char *pszDigestUri, IN HASHHEX HEntity, OUT HASHHEX Response)
Definition httpdigest.c:107