1
+ /**
2
+ * Provides classes modeling parts of the Ruby `OpenSSL` library, which wraps
3
+ * the OpenSSL C library.
4
+ */
5
+
1
6
private import CryptoAlgorithms:: AlgorithmNames
2
7
3
8
bindingset [ algorithmString]
@@ -56,11 +61,14 @@ string getSecureAlgorithmRegex() {
56
61
result = algorithmRegex ( secureAlgorithmString ( max ( int i | exists ( rankedSecureAlgorithm ( i ) ) ) ) )
57
62
}
58
63
59
- private module Ciphers {
64
+ module Ciphers {
60
65
/**
61
- * A known `OpenSSL::Cipher`. Supported ciphers depend on the version of
62
- * `OpenSSL` installed on a system. In the general case, a name will include
63
- * the cipher name, the key length, and the block encryption mode.
66
+ * Holds if `name` is a known `OpenSSL::Cipher`. Supported ciphers depend on the
67
+ * version of `OpenSSL` or `LibreSSL` specified when installing the `openssl` gem.
68
+ * Ciphers listed here are sourced from OpenSSL 1.1.1 and LibreSSL 3.4.1.
69
+ *
70
+ * In the general case, a name will include the cipher name, the key length,
71
+ * and the block encryption mode.
64
72
*
65
73
* Note that since the cipher name itself always comes first in these names
66
74
* and always uses a "-" to demark to block mode, we can safely uppercase
@@ -71,47 +79,184 @@ private module Ciphers {
71
79
predicate isOpenSSLCipher ( string name ) {
72
80
name =
73
81
[
74
- "AES-128-CBC" , "AES-128-CBC-HMAC-SHA1" , "AES-128-CFB" , "AES-128-CFB1" , "AES-128-CFB8" ,
75
- "AES-128-CTR" , "AES-128-ECB" , "AES-128-OFB" , "AES-128-XTS" , "AES-192-CBC" , "AES-192-CFB" ,
76
- "AES-192-CFB1" , "AES-192-CFB8" , "AES-192-CTR" , "AES-192-ECB" , "AES-192-OFB" , "AES-256-CBC" ,
77
- "AES-256-CBC-HMAC-SHA1" , "AES-256-CFB" , "AES-256-CFB1" , "AES-256-CFB8" , "AES-256-CTR" ,
78
- "AES-256-ECB" , "AES-256-OFB" , "AES-256-XTS" , "AES128" , "AES192" , "AES256" , "BF" , "BF-CBC" ,
79
- "BF-CFB" , "BF-ECB" , "BF-OFB" , "CAMELLIA-128-CBC" , "CAMELLIA-128-CFB" , "CAMELLIA-128-CFB1" ,
80
- "CAMELLIA-128-CFB8" , "CAMELLIA-128-ECB" , "CAMELLIA-128-OFB" , "CAMELLIA-192-CBC" ,
81
- "CAMELLIA-192-CFB" , "CAMELLIA-192-CFB1" , "CAMELLIA-192-CFB8" , "CAMELLIA-192-ECB" ,
82
- "CAMELLIA-192-OFB" , "CAMELLIA-256-CBC" , "CAMELLIA-256-CFB" , "CAMELLIA-256-CFB1" ,
83
- "CAMELLIA-256-CFB8" , "CAMELLIA-256-ECB" , "CAMELLIA-256-OFB" , "CAMELLIA128" , "CAMELLIA192" ,
84
- "CAMELLIA256" , "CAST" , "CAST-cbc" , "CAST5-CBC" , "CAST5-CFB" , "CAST5-ECB" , "CAST5-OFB" ,
85
- "ChaCha" , "DES" , "DES-CBC" , "DES-CFB" , "DES-CFB1" , "DES-CFB8" , "DES-ECB" , "DES-EDE" ,
86
- "DES-EDE-CBC" , "DES-EDE-CFB" , "DES-EDE-OFB" , "DES-EDE3" , "DES-EDE3-CBC" , "DES-EDE3-CFB" ,
87
- "DES-EDE3-CFB1" , "DES-EDE3-CFB8" , "DES-EDE3-OFB" , "DES-OFB" , "DES3" , "DESX" , "DESX-CBC" ,
88
- "GOST 28147-89" , "RC2" , "RC2-40-CBC" , "RC2-64-CBC" , "RC2-CBC" , "RC2-CFB" , "RC2-ECB" ,
89
- "RC2-OFB" , "RC4" , "RC4-40" , "RC4-HMAC-MD5" , "aes-128-cbc" , "aes-128-cbc-hmac-sha1" ,
82
+ "aes-128-cbc" , "aes-128-cbc-hmac-sha1" , "aes-128-cbc-hmac-sha256" , "aes-128-ccm" ,
90
83
"aes-128-cfb" , "aes-128-cfb1" , "aes-128-cfb8" , "aes-128-ctr" , "aes-128-ecb" , "aes-128-gcm" ,
91
- "aes-128-ofb" , "aes-128-xts" , "aes-192-cbc" , "aes-192-cfb" , "aes-192-cfb1" , "aes-192-cfb8" ,
92
- "aes-192-ctr" , "aes-192-ecb" , "aes-192-gcm" , "aes-192-ofb" , "aes-256-cbc" ,
93
- "aes-256-cbc-hmac-sha1" , "aes-256-cfb" , "aes-256-cfb1" , "aes-256-cfb8" , "aes-256-ctr" ,
94
- "aes-256-ecb" , "aes-256-gcm" , "aes-256-ofb" , "aes-256-xts" , "aes128" , "aes192" , "aes256" ,
95
- "bf" , "bf-cbc" , "bf-cfb" , "bf-ecb" , "bf-ofb" , "blowfish" , "camellia-128-cbc" ,
96
- "camellia-128-cfb" , "camellia-128-cfb1" , "camellia-128-cfb8" , "camellia-128-ecb" ,
97
- "camellia-128-ofb" , "camellia-192-cbc" , "camellia-192-cfb" , "camellia-192-cfb1" ,
98
- "camellia-192-cfb8" , "camellia-192-ecb" , "camellia-192-ofb" , "camellia-256-cbc" ,
99
- "camellia-256-cfb" , "camellia-256-cfb1" , "camellia-256-cfb8" , "camellia-256-ecb" ,
100
- "camellia-256-ofb" , "camellia128" , "camellia192" , "camellia256" , "cast" , "cast-cbc" ,
101
- "cast5-cbc" , "cast5-cfb" , "cast5-ecb" , "cast5-ofb" , "chacha" , "des" , "des-cbc" , "des-cfb" ,
102
- "des-cfb1" , "des-cfb8" , "des-ecb" , "des-ede" , "des-ede-cbc" , "des-ede-cfb" , "des-ede-ofb" ,
103
- "des-ede3" , "des-ede3-cbc" , "des-ede3-cfb" , "des-ede3-cfb1" , "des-ede3-cfb8" ,
104
- "des-ede3-ofb" , "des-ofb" , "des3" , "desx" , "desx-cbc" , "gost89" , "gost89-cnt" , "gost89-ecb" ,
105
- "id-aes128-GCM" , "id-aes192-GCM" , "id-aes256-GCM" , "rc2" , "rc2-40-cbc" , "rc2-64-cbc" ,
106
- "rc2-cbc" , "rc2-cfb" , "rc2-ecb" , "rc2-ofb" , "rc4" , "rc4-40" , "rc4-hmac-md5"
84
+ "aes-128-ocb" , "aes-128-ofb" , "aes-128-xts" , "aes-192-cbc" , "aes-192-ccm" , "aes-192-cfb" ,
85
+ "aes-192-cfb1" , "aes-192-cfb8" , "aes-192-ctr" , "aes-192-ecb" , "aes-192-gcm" , "aes-192-ocb" ,
86
+ "aes-192-ofb" , "aes-256-cbc" , "aes-256-cbc-hmac-sha1" , "aes-256-cbc-hmac-sha256" ,
87
+ "aes-256-ccm" , "aes-256-cfb" , "aes-256-cfb1" , "aes-256-cfb8" , "aes-256-ctr" , "aes-256-ecb" ,
88
+ "aes-256-gcm" , "aes-256-ocb" , "aes-256-ofb" , "aes-256-xts" , "aes128" , "aes192" , "aes256" ,
89
+ "aria-128-cbc" , "aria-128-ccm" , "aria-128-cfb" , "aria-128-cfb1" , "aria-128-cfb8" ,
90
+ "aria-128-ctr" , "aria-128-ecb" , "aria-128-gcm" , "aria-128-ofb" , "aria-192-cbc" ,
91
+ "aria-192-ccm" , "aria-192-cfb" , "aria-192-cfb1" , "aria-192-cfb8" , "aria-192-ctr" ,
92
+ "aria-192-ecb" , "aria-192-gcm" , "aria-192-ofb" , "aria-256-cbc" , "aria-256-ccm" ,
93
+ "aria-256-cfb" , "aria-256-cfb1" , "aria-256-cfb8" , "aria-256-ctr" , "aria-256-ecb" ,
94
+ "aria-256-gcm" , "aria-256-ofb" , "aria128" , "aria192" , "aria256" , "bf" , "bf-cbc" , "bf-cfb" ,
95
+ "bf-ecb" , "bf-ofb" , "blowfish" , "camellia-128-cbc" , "camellia-128-cfb" , "camellia-128-cfb1" ,
96
+ "camellia-128-cfb8" , "camellia-128-ctr" , "camellia-128-ecb" , "camellia-128-ofb" ,
97
+ "camellia-192-cbc" , "camellia-192-cfb" , "camellia-192-cfb1" , "camellia-192-cfb8" ,
98
+ "camellia-192-ctr" , "camellia-192-ecb" , "camellia-192-ofb" , "camellia-256-cbc" ,
99
+ "camellia-256-cfb" , "camellia-256-cfb1" , "camellia-256-cfb8" , "camellia-256-ctr" ,
100
+ "camellia-256-ecb" , "camellia-256-ofb" , "camellia128" , "camellia192" , "camellia256" , "cast" ,
101
+ "cast-cbc" , "cast5-cbc" , "cast5-cfb" , "cast5-ecb" , "cast5-ofb" , "chacha20" ,
102
+ "chacha20-poly1305" , "des" , "des-cbc" , "des-cfb" , "des-cfb1" , "des-cfb8" , "des-ecb" ,
103
+ "des-ede" , "des-ede-cbc" , "des-ede-cfb" , "des-ede-ecb" , "des-ede-ofb" , "des-ede3" ,
104
+ "des-ede3-cbc" , "des-ede3-cfb" , "des-ede3-cfb1" , "des-ede3-cfb8" , "des-ede3-ecb" ,
105
+ "des-ede3-ofb" , "des-ofb" , "des3" , "desx" , "desx-cbc" , "id-aes128-CCM" , "id-aes128-GCM" ,
106
+ "id-aes192-CCM" , "id-aes192-GCM" , "id-aes256-CCM" , "id-aes256-GCM" , "idea" , "idea-cbc" ,
107
+ "idea-cfb" , "idea-ecb" , "idea-ofb" , "rc2" , "rc2-128" , "rc2-40" , "rc2-40-cbc" , "rc2-64" ,
108
+ "rc2-64-cbc" , "rc2-cbc" , "rc2-cfb" , "rc2-ecb" , "rc2-ofb" , "rc4" , "rc4-40" , "rc4-hmac-md5" ,
109
+ "seed" , "seed-cbc" , "seed-cfb" , "seed-ecb" , "seed-ofb" , "sm4" , "sm4-cbc" , "sm4-cfb" ,
110
+ "sm4-ctr" , "sm4-ecb" , "sm4-ofb" , "AES-128-CBC" , "AES-128-CBC-HMAC-SHA1" , "AES-128-CFB" ,
111
+ "AES-128-CFB1" , "AES-128-CFB8" , "AES-128-CTR" , "AES-128-ECB" , "AES-128-OFB" , "AES-128-XTS" ,
112
+ "AES-192-CBC" , "AES-192-CFB" , "AES-192-CFB1" , "AES-192-CFB8" , "AES-192-CTR" , "AES-192-ECB" ,
113
+ "AES-192-OFB" , "AES-256-CBC" , "AES-256-CBC-HMAC-SHA1" , "AES-256-CFB" , "AES-256-CFB1" ,
114
+ "AES-256-CFB8" , "AES-256-CTR" , "AES-256-ECB" , "AES-256-OFB" , "AES-256-XTS" , "AES128" ,
115
+ "AES192" , "AES256" , "BF" , "BF-CBC" , "BF-CFB" , "BF-ECB" , "BF-OFB" , "CAMELLIA-128-CBC" ,
116
+ "CAMELLIA-128-CFB" , "CAMELLIA-128-CFB1" , "CAMELLIA-128-CFB8" , "CAMELLIA-128-ECB" ,
117
+ "CAMELLIA-128-OFB" , "CAMELLIA-192-CBC" , "CAMELLIA-192-CFB" , "CAMELLIA-192-CFB1" ,
118
+ "CAMELLIA-192-CFB8" , "CAMELLIA-192-ECB" , "CAMELLIA-192-OFB" , "CAMELLIA-256-CBC" ,
119
+ "CAMELLIA-256-CFB" , "CAMELLIA-256-CFB1" , "CAMELLIA-256-CFB8" , "CAMELLIA-256-ECB" ,
120
+ "CAMELLIA-256-OFB" , "CAMELLIA128" , "CAMELLIA192" , "CAMELLIA256" , "CAST" , "CAST-cbc" ,
121
+ "CAST5-CBC" , "CAST5-CFB" , "CAST5-ECB" , "CAST5-OFB" , "ChaCha" , "DES" , "DES-CBC" , "DES-CFB" ,
122
+ "DES-CFB1" , "DES-CFB8" , "DES-ECB" , "DES-EDE" , "DES-EDE-CBC" , "DES-EDE-CFB" , "DES-EDE-OFB" ,
123
+ "DES-EDE3" , "DES-EDE3-CBC" , "DES-EDE3-CFB" , "DES-EDE3-CFB1" , "DES-EDE3-CFB8" ,
124
+ "DES-EDE3-OFB" , "DES-OFB" , "DES3" , "DESX" , "DESX-CBC" , "GOST 28147-89" , "IDEA" , "IDEA-CBC" ,
125
+ "IDEA-CFB" , "IDEA-ECB" , "IDEA-OFB" , "RC2" , "RC2-40-CBC" , "RC2-64-CBC" , "RC2-CBC" , "RC2-CFB" ,
126
+ "RC2-ECB" , "RC2-OFB" , "RC4" , "RC4-40" , "RC4-HMAC-MD5" , "SM4" , "SM4-CBC" , "SM4-CFB" ,
127
+ "SM4-CTR" , "SM4-ECB" , "SM4-OFB" , "chacha" , "gost89" , "gost89-cnt" , "gost89-ecb"
107
128
]
108
129
}
109
130
131
+ /**
132
+ * Gets the canonical cipher name in cases where this isn't simply an
133
+ * upcased version of the provided name. This may be because a default block
134
+ * mode is appended, or due to some other normalization.
135
+ */
136
+ private string getSpecialCanonicalCipherName ( string name ) {
137
+ name = "AES128" and result = "AES-128-CBC"
138
+ or
139
+ name = "AES192" and result = "AES-192-CBC"
140
+ or
141
+ name = "AES256" and result = "AES-256-CBC"
142
+ or
143
+ name = "BF" and result = "BF-CBC"
144
+ or
145
+ name = "CAMELLIA128" and result = "CAMELLIA-128-CBC"
146
+ or
147
+ name = "CAMELLIA192" and result = "CAMELLIA-192-CBC"
148
+ or
149
+ name = "CAMELLIA256" and result = "CAMELLIA-256-CBC"
150
+ or
151
+ name = "CAST" and result = "CAST5-CBC"
152
+ or
153
+ name = "CAST-cbc" and result = "CAST5-CBC"
154
+ or
155
+ name = "ChaCha" and result = "ChaCha"
156
+ or
157
+ name = "DES" and result = "DES-CBC"
158
+ or
159
+ name = "DES3" and result = "DES-EDE3-CBC"
160
+ or
161
+ name = "DESX" and result = "DESX-CBC"
162
+ or
163
+ name = "GOST 28147-89" and result = "gost89"
164
+ or
165
+ name = "IDEA" and result = "IDEA-CBC"
166
+ or
167
+ name = "RC2" and result = "RC2-CBC"
168
+ or
169
+ name = "SM4" and result = "SM4-CBC"
170
+ or
171
+ name = "aes-128-ccm" and result = "id-aes128-CCM"
172
+ or
173
+ name = "aes-128-gcm" and result = "id-aes128-GCM"
174
+ or
175
+ name = "aes-192-ccm" and result = "id-aes192-CCM"
176
+ or
177
+ name = "aes-192-gcm" and result = "id-aes192-GCM"
178
+ or
179
+ name = "aes-256-ccm" and result = "id-aes256-CCM"
180
+ or
181
+ name = "aes-256-gcm" and result = "id-aes256-GCM"
182
+ or
183
+ name = "aes128" and result = "AES-128-CBC"
184
+ or
185
+ name = "aes192" and result = "AES-192-CBC"
186
+ or
187
+ name = "aes256" and result = "AES-256-CBC"
188
+ or
189
+ name = "bf" and result = "BF-CBC"
190
+ or
191
+ name = "blowfish" and result = "BF-CBC"
192
+ or
193
+ name = "camellia128" and result = "CAMELLIA-128-CBC"
194
+ or
195
+ name = "camellia192" and result = "CAMELLIA-192-CBC"
196
+ or
197
+ name = "camellia256" and result = "CAMELLIA-256-CBC"
198
+ or
199
+ name = "cast" and result = "CAST5-CBC"
200
+ or
201
+ name = "cast-cbc" and result = "CAST5-CBC"
202
+ or
203
+ name = "chacha" and result = "ChaCha"
204
+ or
205
+ name = "des" and result = "DES-CBC"
206
+ or
207
+ name = "des3" and result = "DES-EDE3-CBC"
208
+ or
209
+ name = "desx" and result = "DESX-CBC"
210
+ or
211
+ name = "gost89" and result = "gost89"
212
+ or
213
+ name = "gost89-cnt" and result = "gost89-cnt"
214
+ or
215
+ name = "gost89-ecb" and result = "gost89-ecb"
216
+ or
217
+ name = "id-aes128-CCM" and result = "id-aes128-CCM"
218
+ or
219
+ name = "id-aes128-GCM" and result = "id-aes128-GCM"
220
+ or
221
+ name = "id-aes192-CCM" and result = "id-aes192-CCM"
222
+ or
223
+ name = "id-aes192-GCM" and result = "id-aes192-GCM"
224
+ or
225
+ name = "id-aes256-CCM" and result = "id-aes256-CCM"
226
+ or
227
+ name = "id-aes256-GCM" and result = "id-aes256-GCM"
228
+ or
229
+ name = "idea" and result = "IDEA-CBC"
230
+ or
231
+ name = "rc2" and result = "RC2-CBC"
232
+ or
233
+ name = "sm4" and result = "SM4-CBC"
234
+ }
235
+
236
+ /**
237
+ * Gets the canonical version of `name`, as reported by `OpenSSL::Cipher#name`.
238
+ * No result if `name` is not a known OpenSSL cipher name.
239
+ */
240
+ string getCanonicalCipherName ( string name ) {
241
+ isOpenSSLCipher ( name ) and
242
+ (
243
+ if exists ( string special | special = getSpecialCanonicalCipherName ( name ) )
244
+ then result = getSpecialCanonicalCipherName ( name )
245
+ else result = name .toUpperCase ( )
246
+ )
247
+ }
248
+
249
+ /**
250
+ * Holds if `name` is the name of an OpenSSL cipher that is known to be weak.
251
+ */
110
252
predicate isWeakOpenSSLCipher ( string name ) {
111
253
isOpenSSLCipher ( name ) and
112
254
name .toUpperCase ( ) .regexpMatch ( getInsecureAlgorithmRegex ( ) )
113
255
}
114
256
257
+ /**
258
+ * Holds if `name` is the name of an OpenSSL cipher that is known to be strong.
259
+ */
115
260
predicate isStrongOpenSSLCipher ( string name ) {
116
261
isOpenSSLCipher ( name ) and
117
262
name .toUpperCase ( ) .regexpMatch ( getSecureAlgorithmRegex ( ) ) and
@@ -142,9 +287,19 @@ class OpenSSLCipher extends MkOpenSSLCipher {
142
287
143
288
OpenSSLCipher ( ) { this = MkOpenSSLCipher ( name , isWeak ) }
144
289
290
+ /**
291
+ * Gets a name of this cipher.
292
+ */
145
293
string getName ( ) { result = name }
146
294
295
+ /**
296
+ * Gets a name of this cipher in canonical form.
297
+ */
298
+ string getCanonicalName ( ) { result = getCanonicalCipherName ( this .getName ( ) ) }
299
+
300
+ /** Holds if this algorithm is weak. */
147
301
predicate isWeak ( ) { isWeak = true }
148
302
149
- string toString ( ) { result = this .getName ( ) }
303
+ /** Gets a textual representation of this element. */
304
+ string toString ( ) { result = this .getCanonicalName ( ) }
150
305
}
0 commit comments