@@ -149,6 +149,62 @@ read_file_and_null_terminate (const char *filename, size_t *out_len)
149
149
}
150
150
151
151
152
+ // `decode_object` decodes a cryptographic object from a blob.
153
+ // Returns NULL on error.
154
+ static LPBYTE
155
+ decode_object (const char * structType ,
156
+ const LPBYTE data ,
157
+ DWORD data_len ,
158
+ DWORD * out_len ,
159
+ const char * descriptor ,
160
+ const char * filename )
161
+ {
162
+ BSON_ASSERT_PARAM (structType );
163
+ BSON_ASSERT_PARAM (data );
164
+ BSON_ASSERT_PARAM (structType );
165
+ BSON_ASSERT_PARAM (out_len );
166
+ BSON_ASSERT_PARAM (descriptor );
167
+ BSON_ASSERT_PARAM (filename );
168
+ // Get needed output length:
169
+ if (!CryptDecodeObjectEx (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , /* dwCertEncodingType */
170
+ structType , /* lpszStructType */
171
+ data , /* pbEncoded */
172
+ data_len , /* cbEncoded */
173
+ 0 , /* dwFlags */
174
+ NULL , /* pDecodePara */
175
+ NULL , /* pvStructInfo */
176
+ out_len /* pcbStructInfo */
177
+ )) {
178
+ char * msg = mongoc_winerr_to_string (GetLastError ());
179
+ MONGOC_ERROR ("Failed to decode %s from '%s': %s" , descriptor , filename , msg );
180
+ bson_free (msg );
181
+ return NULL ;
182
+ }
183
+
184
+ if (* out_len == 0 ) {
185
+ return NULL ;
186
+ }
187
+ LPBYTE out = (LPBYTE ) bson_malloc (* out_len );
188
+
189
+ if (!CryptDecodeObjectEx (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , /* dwCertEncodingType */
190
+ structType , /* lpszStructType */
191
+ data , /* pbEncoded */
192
+ data_len , /* cbEncoded */
193
+ 0 , /* dwFlags */
194
+ NULL , /* pDecodePara */
195
+ out , /* pvStructInfo */
196
+ out_len /* pcbStructInfo */
197
+ )) {
198
+ char * msg = mongoc_winerr_to_string (GetLastError ());
199
+ MONGOC_ERROR ("Failed to decode %s from '%s': %s" , descriptor , filename , msg );
200
+ bson_free (msg );
201
+ bson_free (out );
202
+ return NULL ;
203
+ }
204
+
205
+ return out ;
206
+ }
207
+
152
208
PCCERT_CONTEXT
153
209
mongoc_secure_channel_setup_certificate_from_file (const char * filename )
154
210
{
@@ -161,9 +217,11 @@ mongoc_secure_channel_setup_certificate_from_file (const char *filename)
161
217
LPBYTE encoded_cert = NULL ;
162
218
const char * pem_public ;
163
219
const char * pem_private ;
164
- LPBYTE blob_private = NULL ;
165
220
PCCERT_CONTEXT cert = NULL ;
221
+ LPBYTE blob_private = NULL ;
166
222
DWORD blob_private_len = 0 ;
223
+ LPBYTE blob_private_rsa = NULL ;
224
+ DWORD blob_private_rsa_len = 0 ;
167
225
DWORD encoded_private_len = 0 ;
168
226
LPBYTE encoded_private = NULL ;
169
227
@@ -185,16 +243,6 @@ mongoc_secure_channel_setup_certificate_from_file (const char *filename)
185
243
goto fail ;
186
244
}
187
245
188
- pem_private = strstr (pem , "-----BEGIN RSA PRIVATE KEY-----" );
189
- if (!pem_private ) {
190
- pem_private = strstr (pem , "-----BEGIN PRIVATE KEY-----" );
191
- }
192
-
193
- if (!pem_private ) {
194
- MONGOC_ERROR ("Can't find private key in '%s'" , filename );
195
- goto fail ;
196
- }
197
-
198
246
encoded_cert = decode_pem_base64 (pem_public , & encoded_cert_len , "public key" , filename );
199
247
if (!encoded_cert ) {
200
248
goto fail ;
@@ -208,43 +256,47 @@ mongoc_secure_channel_setup_certificate_from_file (const char *filename)
208
256
goto fail ;
209
257
}
210
258
211
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa380285%28v=vs.85%29.aspx
212
- */
213
- encoded_private = decode_pem_base64 (pem_private , & encoded_private_len , "private key" , filename );
214
- if (!encoded_private ) {
215
- goto fail ;
216
- }
259
+ if (NULL != (pem_private = strstr (pem , "-----BEGIN RSA PRIVATE KEY-----" ))) {
260
+ encoded_private = decode_pem_base64 (pem_private , & encoded_private_len , "private key" , filename );
261
+ if (!encoded_private ) {
262
+ goto fail ;
263
+ }
217
264
218
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa379912%28v=vs.85%29.aspx
219
- */
220
- success = CryptDecodeObjectEx (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , /* dwCertEncodingType */
221
- PKCS_RSA_PRIVATE_KEY , /* lpszStructType */
222
- encoded_private , /* pbEncoded */
223
- encoded_private_len , /* cbEncoded */
224
- 0 , /* dwFlags */
225
- NULL , /* pDecodePara */
226
- NULL , /* pvStructInfo */
227
- & blob_private_len ); /* pcbStructInfo */
228
- if (!success ) {
229
- char * msg = mongoc_winerr_to_string (GetLastError ());
230
- MONGOC_ERROR ("Failed to parse private key. %s" , msg );
231
- bson_free (msg );
232
- goto fail ;
233
- }
265
+ blob_private_rsa = decode_object (
266
+ PKCS_RSA_PRIVATE_KEY , encoded_private , encoded_private_len , & blob_private_rsa_len , "private key" , filename );
267
+ if (!blob_private_rsa ) {
268
+ goto fail ;
269
+ }
270
+ } else if (NULL != (pem_private = strstr (pem , "-----BEGIN PRIVATE KEY-----" ))) {
271
+ encoded_private = decode_pem_base64 (pem_private , & encoded_private_len , "private key" , filename );
272
+ if (!encoded_private ) {
273
+ goto fail ;
274
+ }
234
275
235
- blob_private = (LPBYTE ) bson_malloc0 (blob_private_len );
236
- success = CryptDecodeObjectEx (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
237
- PKCS_RSA_PRIVATE_KEY ,
238
- encoded_private ,
239
- encoded_private_len ,
240
- 0 ,
241
- NULL ,
242
- blob_private ,
243
- & blob_private_len );
244
- if (!success ) {
245
- char * msg = mongoc_winerr_to_string (GetLastError ());
246
- MONGOC_ERROR ("Failed to parse private key: %s" , msg );
247
- bson_free (msg );
276
+ blob_private = decode_object (
277
+ PKCS_PRIVATE_KEY_INFO , encoded_private , encoded_private_len , & blob_private_len , "private key" , filename );
278
+ if (!blob_private ) {
279
+ goto fail ;
280
+ }
281
+
282
+ // Have PrivateKey. Get RSA key from it.
283
+ CRYPT_PRIVATE_KEY_INFO * privateKeyInfo = (CRYPT_PRIVATE_KEY_INFO * ) blob_private ;
284
+ if (strcmp (privateKeyInfo -> Algorithm .pszObjId , szOID_RSA_RSA ) != 0 ) {
285
+ MONGOC_ERROR ("Non-RSA private keys are not supported" );
286
+ goto fail ;
287
+ }
288
+
289
+ blob_private_rsa = decode_object (PKCS_RSA_PRIVATE_KEY ,
290
+ privateKeyInfo -> PrivateKey .pbData ,
291
+ privateKeyInfo -> PrivateKey .cbData ,
292
+ & blob_private_rsa_len ,
293
+ "private key" ,
294
+ filename );
295
+ if (!blob_private_rsa ) {
296
+ goto fail ;
297
+ }
298
+ } else {
299
+ MONGOC_ERROR ("Can't find private key in '%s'" , filename );
248
300
goto fail ;
249
301
}
250
302
@@ -265,12 +317,12 @@ mongoc_secure_channel_setup_certificate_from_file (const char *filename)
265
317
HCRYPTKEY hKey ;
266
318
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa380207%28v=vs.85%29.aspx
267
319
*/
268
- success = CryptImportKey (provider , /* hProv */
269
- blob_private , /* pbData */
270
- blob_private_len , /* dwDataLen */
271
- 0 , /* hPubKey */
272
- 0 , /* dwFlags */
273
- & hKey ); /* phKey, OUT */
320
+ success = CryptImportKey (provider , /* hProv */
321
+ blob_private_rsa , /* pbData */
322
+ blob_private_rsa_len , /* dwDataLen */
323
+ 0 , /* hPubKey */
324
+ 0 , /* dwFlags */
325
+ & hKey ); /* phKey, OUT */
274
326
if (!success ) {
275
327
char * msg = mongoc_winerr_to_string (GetLastError ());
276
328
MONGOC_ERROR ("CryptImportKey for private key failed: %s" , msg );
@@ -308,6 +360,11 @@ mongoc_secure_channel_setup_certificate_from_file (const char *filename)
308
360
bson_free (encoded_private );
309
361
}
310
362
363
+ if (blob_private_rsa ) {
364
+ SecureZeroMemory (blob_private_rsa , blob_private_rsa_len );
365
+ bson_free (blob_private_rsa );
366
+ }
367
+
311
368
if (blob_private ) {
312
369
SecureZeroMemory (blob_private , blob_private_len );
313
370
bson_free (blob_private );
0 commit comments