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-2023 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 
35 static 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 */
69 void
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 */
106 void
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 */
DigestCalcResponse
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
md_ctx_t
mbedtls_md_context_t md_ctx_t
Generic message digest context.
Definition: crypto_mbedtls.h:43
CvtHex
static void CvtHex(IN HASH Bin, OUT HASHHEX Hex)
Definition: httpdigest.c:36
DigestCalcHA1
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
md_ctx_new
md_ctx_t * md_ctx_new(void)
Definition: crypto_openssl.c:1108
md_ctx_final
void md_ctx_final(md_ctx_t *ctx, uint8_t *dst)
md_ctx_cleanup
void md_ctx_cleanup(md_ctx_t *ctx)
crypto.h
httpdigest.h
md_ctx_update
void md_ctx_update(md_ctx_t *ctx, const uint8_t *src, int src_len)
md_ctx_init
void md_ctx_init(md_ctx_t *ctx, const char *mdname)
Initialises the given message digest context.
syshead.h
md_ctx_free
void md_ctx_free(md_ctx_t *ctx)
config.h