Skip to content

Commit eb9f9de

Browse files
committed
md5: allow disabling old-style encrypted private keys at build-time
Before this patch, this happened at runtime when using an old (pre-3.0), FIPS-enabled OpenSSL backend. This patch makes it possible to disable this via the build-time option `LIBSSH2_NO_MD5_PEM`. Also: - make sure to exclude all MD5 internal APIs when both the above and `LIBSSH2_NO_MD5` are enabled. - fix tests to support build with`LIBSSH2_NO_MD5`, `LIBSSH2_NO_MD5_PEM` and `LIBSSH2_NO_3DES`. - add FIXME to apply this change to `os400qc3.*`. Old-style encrypted private keys require MD5 and they look like this: ``` -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,<MD5-hex> <base64> -----END RSA PRIVATE KEY----- ``` E.g.: `tests/key_rsa_encrypted` Ref: libssh2/www#20 Closes libssh2#1181
1 parent 4a64ca1 commit eb9f9de

15 files changed

+170
-79
lines changed

Diff for: .github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ jobs:
322322
- name: 'make build'
323323
if: ${{ matrix.build == 'make' }}
324324
env:
325-
CPPFLAGS: -DLIBSSH2_NO_MD5 -DLIBSSH2_NO_HMAC_RIPEMD -DLIBSSH2_NO_DSA -DLIBSSH2_NO_AES_CBC -DLIBSSH2_NO_AES_CTR -DLIBSSH2_NO_BLOWFISH -DLIBSSH2_NO_RC4 -DLIBSSH2_NO_CAST -DLIBSSH2_NO_3DES
325+
CPPFLAGS: -DLIBSSH2_NO_MD5 -DLIBSSH2_NO_MD5_PEM -DLIBSSH2_NO_HMAC_RIPEMD -DLIBSSH2_NO_DSA -DLIBSSH2_NO_AES_CBC -DLIBSSH2_NO_AES_CTR -DLIBSSH2_NO_BLOWFISH -DLIBSSH2_NO_RC4 -DLIBSSH2_NO_CAST -DLIBSSH2_NO_3DES
326326
LIBSSH2_CPPFLAGS_LIB: -DLIBSSH2_EXPORTS
327327
ZLIB_PATH: /${{ matrix.sys }}
328328
OPENSSL_PATH: /${{ matrix.sys }}

Diff for: src/Makefile.inc

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ HHEADERS = \
2929
channel.h \
3030
comp.h \
3131
crypto.h \
32+
crypto_config.h \
3233
libgcrypt.h \
3334
libssh2_priv.h \
3435
libssh2_setup.h \

Diff for: src/crypto.h

-65
Original file line numberDiff line numberDiff line change
@@ -55,71 +55,6 @@
5555
#error "no cryptography backend selected"
5656
#endif
5757

58-
#ifdef LIBSSH2_NO_MD5
59-
#undef LIBSSH2_MD5
60-
#define LIBSSH2_MD5 0
61-
#endif
62-
63-
#ifdef LIBSSH2_NO_HMAC_RIPEMD
64-
#undef LIBSSH2_HMAC_RIPEMD
65-
#define LIBSSH2_HMAC_RIPEMD 0
66-
#endif
67-
68-
#ifdef LIBSSH2_NO_DSA
69-
#undef LIBSSH2_DSA
70-
#define LIBSSH2_DSA 0
71-
#endif
72-
73-
#ifdef LIBSSH2_NO_RSA
74-
#undef LIBSSH2_RSA
75-
#define LIBSSH2_RSA 0
76-
#endif
77-
78-
#ifdef LIBSSH2_NO_RSA_SHA1
79-
#undef LIBSSH2_RSA_SHA1
80-
#define LIBSSH2_RSA_SHA1 0
81-
#endif
82-
83-
#ifdef LIBSSH2_NO_ECDSA
84-
#undef LIBSSH2_ECDSA
85-
#define LIBSSH2_ECDSA 0
86-
#endif
87-
88-
#ifdef LIBSSH2_NO_ED25519
89-
#undef LIBSSH2_ED25519
90-
#define LIBSSH2_ED25519 0
91-
#endif
92-
93-
#ifdef LIBSSH2_NO_AES_CTR
94-
#undef LIBSSH2_AES_CTR
95-
#define LIBSSH2_AES_CTR 0
96-
#endif
97-
98-
#ifdef LIBSSH2_NO_AES_CBC
99-
#undef LIBSSH2_AES_CBC
100-
#define LIBSSH2_AES_CBC 0
101-
#endif
102-
103-
#ifdef LIBSSH2_NO_BLOWFISH
104-
#undef LIBSSH2_BLOWFISH
105-
#define LIBSSH2_BLOWFISH 0
106-
#endif
107-
108-
#ifdef LIBSSH2_NO_RC4
109-
#undef LIBSSH2_RC4
110-
#define LIBSSH2_RC4 0
111-
#endif
112-
113-
#ifdef LIBSSH2_NO_CAST
114-
#undef LIBSSH2_CAST
115-
#define LIBSSH2_CAST 0
116-
#endif
117-
118-
#ifdef LIBSSH2_NO_3DES
119-
#undef LIBSSH2_3DES
120-
#define LIBSSH2_3DES 0
121-
#endif
122-
12358
#define LIBSSH2_ED25519_KEY_LEN 32
12459
#define LIBSSH2_ED25519_PRIVATE_KEY_LEN 64
12560
#define LIBSSH2_ED25519_SIG_LEN 64

Diff for: src/crypto_config.h

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* Copyright (C) Viktor Szakats
2+
*
3+
* SPDX-License-Identifier: BSD-3-Clause
4+
*/
5+
6+
#define LIBSSH2_MD5_PEM LIBSSH2_MD5
7+
8+
#ifdef LIBSSH2_NO_MD5
9+
#undef LIBSSH2_MD5
10+
#define LIBSSH2_MD5 0
11+
#endif
12+
13+
#ifdef LIBSSH2_NO_MD5_PEM
14+
#undef LIBSSH2_MD5_PEM
15+
#define LIBSSH2_MD5_PEM 0
16+
#endif
17+
18+
#ifdef LIBSSH2_NO_HMAC_RIPEMD
19+
#undef LIBSSH2_HMAC_RIPEMD
20+
#define LIBSSH2_HMAC_RIPEMD 0
21+
#endif
22+
23+
#ifdef LIBSSH2_NO_DSA
24+
#undef LIBSSH2_DSA
25+
#define LIBSSH2_DSA 0
26+
#endif
27+
28+
#ifdef LIBSSH2_NO_RSA
29+
#undef LIBSSH2_RSA
30+
#define LIBSSH2_RSA 0
31+
#endif
32+
33+
#ifdef LIBSSH2_NO_RSA_SHA1
34+
#undef LIBSSH2_RSA_SHA1
35+
#define LIBSSH2_RSA_SHA1 0
36+
#endif
37+
38+
#ifdef LIBSSH2_NO_ECDSA
39+
#undef LIBSSH2_ECDSA
40+
#define LIBSSH2_ECDSA 0
41+
#endif
42+
43+
#ifdef LIBSSH2_NO_ED25519
44+
#undef LIBSSH2_ED25519
45+
#define LIBSSH2_ED25519 0
46+
#endif
47+
48+
#ifdef LIBSSH2_NO_AES_CTR
49+
#undef LIBSSH2_AES_CTR
50+
#define LIBSSH2_AES_CTR 0
51+
#endif
52+
53+
#ifdef LIBSSH2_NO_AES_CBC
54+
#undef LIBSSH2_AES_CBC
55+
#define LIBSSH2_AES_CBC 0
56+
#endif
57+
58+
#ifdef LIBSSH2_NO_BLOWFISH
59+
#undef LIBSSH2_BLOWFISH
60+
#define LIBSSH2_BLOWFISH 0
61+
#endif
62+
63+
#ifdef LIBSSH2_NO_RC4
64+
#undef LIBSSH2_RC4
65+
#define LIBSSH2_RC4 0
66+
#endif
67+
68+
#ifdef LIBSSH2_NO_CAST
69+
#undef LIBSSH2_CAST
70+
#define LIBSSH2_CAST 0
71+
#endif
72+
73+
#ifdef LIBSSH2_NO_3DES
74+
#undef LIBSSH2_3DES
75+
#define LIBSSH2_3DES 0
76+
#endif

Diff for: src/libgcrypt.h

+8
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@
6666
#define LIBSSH2_ECDSA 0
6767
#define LIBSSH2_ED25519 0
6868

69+
#include "crypto_config.h"
70+
71+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
6972
#define MD5_DIGEST_LENGTH 16
73+
#endif
7074
#define SHA_DIGEST_LENGTH 20
7175
#define SHA256_DIGEST_LENGTH 32
7276
#define SHA384_DIGEST_LENGTH 48
@@ -124,6 +128,7 @@
124128
#define libssh2_sha512(message, len, out) \
125129
gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len)
126130

131+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
127132
#define libssh2_md5_ctx gcry_md_hd_t
128133

129134
/* returns 0 in case of failure */
@@ -136,15 +141,18 @@
136141
memcpy(out, gcry_md_read(ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close(ctx)
137142
#define libssh2_md5(message, len, out) \
138143
gcry_md_hash_buffer(GCRY_MD_MD5, out, message, len)
144+
#endif
139145

140146
#define libssh2_hmac_ctx gcry_md_hd_t
141147
#define libssh2_hmac_ctx_init(ctx)
142148
#define libssh2_hmac_sha1_init(ctx, key, keylen) \
143149
gcry_md_open(ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC), \
144150
gcry_md_setkey(*ctx, key, keylen)
151+
#if LIBSSH2_MD5
145152
#define libssh2_hmac_md5_init(ctx, key, keylen) \
146153
gcry_md_open(ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC), \
147154
gcry_md_setkey(*ctx, key, keylen)
155+
#endif
148156
#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
149157
gcry_md_open(ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \
150158
gcry_md_setkey(*ctx, key, keylen)

Diff for: src/mbedtls.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@
9292
#endif
9393
#define LIBSSH2_ED25519 0
9494

95+
#include "crypto_config.h"
96+
97+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
9598
#define MD5_DIGEST_LENGTH 16
99+
#endif
96100
#define SHA_DIGEST_LENGTH 20
97101
#define SHA256_DIGEST_LENGTH 32
98102
#define SHA384_DIGEST_LENGTH 48
@@ -134,8 +138,10 @@
134138

135139
#define libssh2_hmac_sha1_init(pctx, key, keylen) \
136140
_libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA1, key, keylen)
141+
#if LIBSSH2_MD5
137142
#define libssh2_hmac_md5_init(pctx, key, keylen) \
138143
_libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_MD5, key, keylen)
144+
#endif
139145
#define libssh2_hmac_ripemd160_init(pctx, key, keylen) \
140146
_libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_RIPEMD160, key, keylen)
141147
#define libssh2_hmac_sha256_init(pctx, key, keylen) \
@@ -219,6 +225,7 @@
219225
* mbedTLS backend: MD5 functions
220226
*/
221227

228+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
222229
#define libssh2_md5_ctx mbedtls_md_context_t
223230

224231
#define libssh2_md5_init(pctx) \
@@ -229,7 +236,7 @@
229236
_libssh2_mbedtls_hash_final(&ctx, hash)
230237
#define libssh2_md5(data, datalen, hash) \
231238
_libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_MD5, hash)
232-
239+
#endif
233240

234241
/*******************************************************************/
235242
/*

Diff for: src/openssl.c

+2
Original file line numberDiff line numberDiff line change
@@ -2495,6 +2495,7 @@ _libssh2_sha512(const unsigned char *message, size_t len,
24952495
return 1; /* error */
24962496
}
24972497

2498+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
24982499
int
24992500
_libssh2_md5_init(libssh2_md5_ctx *ctx)
25002501
{
@@ -2530,6 +2531,7 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx)
25302531
return EVP_DigestInit(ctx, EVP_get_digestbyname("md5"));
25312532
#endif
25322533
}
2534+
#endif
25332535

25342536
#if LIBSSH2_ECDSA
25352537

Diff for: src/openssl.h

+4
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@
194194
# define LIBSSH2_3DES 1
195195
#endif
196196

197+
#include "crypto_config.h"
198+
197199
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
198200

199201
#define _libssh2_random(buf, len) \
@@ -296,6 +298,7 @@ int _libssh2_sha512(const unsigned char *message, size_t len,
296298
unsigned char *out);
297299
#define libssh2_sha512(x,y,z) _libssh2_sha512(x,y,z)
298300

301+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
299302
#ifdef HAVE_OPAQUE_STRUCTS
300303
#define libssh2_md5_ctx EVP_MD_CTX *
301304
#else
@@ -315,6 +318,7 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx);
315318
#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len)
316319
#define libssh2_md5_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL)
317320
#endif
321+
#endif
318322

319323
#ifdef HAVE_OPAQUE_STRUCTS
320324
#define libssh2_hmac_ctx HMAC_CTX *

Diff for: src/os400qc3.h

+4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@
164164
#undef Qc3_MK_Pending
165165
#define Qc3_MK_Pending '\xF3' /* '3' */
166166

167+
/* FIXME: Disable MD5 macros/constants and functions when
168+
LIBSSH2_MD5 and LIBSSH_MD5_PEM have the value 0. */
167169

168170
/* Define which features are supported. */
169171
#define LIBSSH2_MD5 1
@@ -186,6 +188,8 @@
186188
#define LIBSSH2_ECDSA 0
187189
#define LIBSSH2_ED25519 0
188190

191+
#include "crypto_config.h"
192+
189193
#define MD5_DIGEST_LENGTH 16
190194
#define SHA_DIGEST_LENGTH 20
191195
#define SHA256_DIGEST_LENGTH 32

Diff for: src/pem.c

+5-6
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,6 @@ static unsigned char hex_decode(char digit)
106106
((digit >= 'A') ? (0xA + (digit - 'A')) : (digit - '0'));
107107
}
108108

109-
/* Hack to fix builds with crypto backends with MD5 support disabled.
110-
FIXME: Honor our LIBSSH2_MD5 macro for MD5-dependent logic. */
111-
#ifdef OPENSSL_NO_MD5
112-
#define MD5_DIGEST_LENGTH 16
113-
#endif
114-
115109
int
116110
_libssh2_pem_parse(LIBSSH2_SESSION * session,
117111
const char *headerbegin,
@@ -215,6 +209,7 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session,
215209
}
216210

217211
if(method) {
212+
#if LIBSSH2_MD5_PEM
218213
/* Set up decryption */
219214
int free_iv = 0, free_secret = 0, len_decrypted = 0, padding = 0;
220215
int blocksize = method->blocksize;
@@ -292,6 +287,10 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session,
292287
/* Clean up */
293288
_libssh2_explicit_zero((char *)secret, sizeof(secret));
294289
method->dtor(session, &abstract);
290+
#else
291+
ret = -1;
292+
goto out;
293+
#endif
295294
}
296295

297296
ret = 0;

Diff for: src/wincng.c

+10
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@
9494
#define BCRYPT_RNG_ALGORITHM L"RNG"
9595
#endif
9696

97+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
9798
#ifndef BCRYPT_MD5_ALGORITHM
9899
#define BCRYPT_MD5_ALGORITHM L"MD5"
99100
#endif
101+
#endif
100102

101103
#ifndef BCRYPT_SHA1_ALGORITHM
102104
#define BCRYPT_SHA1_ALGORITHM L"SHA1"
@@ -254,11 +256,13 @@ _libssh2_wincng_init(void)
254256
_libssh2_wincng.hAlgRNG = NULL;
255257
}
256258

259+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
257260
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5,
258261
BCRYPT_MD5_ALGORITHM, NULL, 0);
259262
if(!BCRYPT_SUCCESS(ret)) {
260263
_libssh2_wincng.hAlgHashMD5 = NULL;
261264
}
265+
#endif
262266
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1,
263267
BCRYPT_SHA1_ALGORITHM, NULL, 0);
264268
if(!BCRYPT_SUCCESS(ret)) {
@@ -280,12 +284,14 @@ _libssh2_wincng_init(void)
280284
_libssh2_wincng.hAlgHashSHA512 = NULL;
281285
}
282286

287+
#if LIBSSH2_MD5
283288
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5,
284289
BCRYPT_MD5_ALGORITHM, NULL,
285290
BCRYPT_ALG_HANDLE_HMAC_FLAG);
286291
if(!BCRYPT_SUCCESS(ret)) {
287292
_libssh2_wincng.hAlgHmacMD5 = NULL;
288293
}
294+
#endif
289295
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1,
290296
BCRYPT_SHA1_ALGORITHM, NULL,
291297
BCRYPT_ALG_HANDLE_HMAC_FLAG);
@@ -395,8 +401,10 @@ _libssh2_wincng_free(void)
395401
{
396402
if(_libssh2_wincng.hAlgRNG)
397403
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRNG, 0);
404+
#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM
398405
if(_libssh2_wincng.hAlgHashMD5)
399406
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashMD5, 0);
407+
#endif
400408
if(_libssh2_wincng.hAlgHashSHA1)
401409
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA1, 0);
402410
if(_libssh2_wincng.hAlgHashSHA256)
@@ -405,8 +413,10 @@ _libssh2_wincng_free(void)
405413
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA384, 0);
406414
if(_libssh2_wincng.hAlgHashSHA512)
407415
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA512, 0);
416+
#if LIBSSH2_MD5
408417
if(_libssh2_wincng.hAlgHmacMD5)
409418
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacMD5, 0);
419+
#endif
410420
if(_libssh2_wincng.hAlgHmacSHA1)
411421
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA1, 0);
412422
if(_libssh2_wincng.hAlgHmacSHA256)

0 commit comments

Comments
 (0)