GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/crypto/signature.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 385 564 68.3%
Branches: 213 592 36.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * This is a wrapper around OpenSSL's libcrypto. It supports
5 * signing of data with an X.509 certificate and verifying
6 * a signature against a certificate. The certificates can act only as key
7 * store, in which case there is no verification against the CA chain.
8 *
9 * It also supports verification of plain RSA signatures (for the whitelist).
10 *
11 * We work exclusively with PEM formatted files (= Base64-encoded DER files).
12 */
13
14 #include "cvmfs_config.h"
15 #include "crypto/signature.h"
16
17 #include <openssl/bn.h>
18 #include <openssl/evp.h>
19 #include <openssl/pkcs7.h>
20 #include <openssl/x509v3.h>
21
22 #include <cassert>
23 #include <cctype>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <string>
28 #include <vector>
29
30 #include "crypto/hash.h"
31 #include "crypto/openssl_version.h"
32 #include "util/concurrency.h"
33 #include "util/logging.h"
34 #include "util/platform.h"
35 #include "util/posix.h"
36 #include "util/prng.h"
37 #include "util/smalloc.h"
38 #include "util/string.h"
39
40 using namespace std; // NOLINT
41
42 namespace signature {
43
44 const char *kDefaultPublicKey = "/etc/cvmfs/keys/cern.ch/cern-it4.pub";
45
46
47 static int CallbackCertVerify(int ok, X509_STORE_CTX *ctx) {
48 LogCvmfs(kLogCvmfs, kLogDebug, "certificate chain verification: %d", ok);
49 if (ok) return ok;
50
51 int error = X509_STORE_CTX_get_error(ctx);
52 X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
53 string subject = "subject n/a";
54 if (current_cert) {
55 char *buffer = NULL;
56 buffer = X509_NAME_oneline(X509_get_subject_name(current_cert), NULL, 0);
57 if (buffer) {
58 subject = string(buffer);
59 free(buffer);
60 }
61 }
62 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
63 "certificate verification error: %s, error %s (%d)",
64 subject.c_str(), X509_verify_cert_error_string(error), error);
65 return ok;
66 }
67
68
69 258 SignatureManager::SignatureManager() {
70 258 private_key_ = NULL;
71 258 private_master_key_ = NULL;
72 258 certificate_ = NULL;
73 258 x509_store_ = NULL;
74 258 x509_lookup_ = NULL;
75 258 int retval = pthread_mutex_init(&lock_blacklist_, NULL);
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 258 times.
258 assert(retval == 0);
77 258 }
78
79
80 248 void SignatureManager::InitX509Store() {
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
248 if (x509_store_) X509_STORE_free(x509_store_);
82 248 x509_lookup_ = NULL;
83 248 x509_store_ = X509_STORE_new();
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
248 assert(x509_store_ != NULL);
85
86 248 unsigned long verify_flags = // NOLINT(runtime/int)
87 X509_V_FLAG_CRL_CHECK |
88 X509_V_FLAG_CRL_CHECK_ALL;
89 #ifdef OPENSSL_API_INTERFACE_V09
90 X509_STORE_set_flags(x509_store_, verify_flags);
91 #else
92 int retval;
93 248 X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
94
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
248 assert(param != NULL);
95 248 retval = X509_VERIFY_PARAM_set_flags(param, verify_flags);
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
248 assert(retval == 1);
97 248 retval = X509_STORE_set1_param(x509_store_, param);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
248 assert(retval == 1);
99 248 X509_VERIFY_PARAM_free(param);
100 #endif
101
102 248 x509_lookup_ = X509_STORE_add_lookup(x509_store_, X509_LOOKUP_hash_dir());
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
248 assert(x509_lookup_ != NULL);
104
105 248 X509_STORE_set_verify_cb_func(x509_store_, CallbackCertVerify);
106 248 }
107
108
109 248 void SignatureManager::Init() {
110 248 OpenSSL_add_all_algorithms();
111 248 InitX509Store();
112 248 }
113
114
115 248 void SignatureManager::Fini() {
116 248 UnloadCertificate();
117 248 UnloadPrivateKey();
118 248 UnloadPrivateMasterKey();
119 248 UnloadPublicRsaKeys();
120 // Lookup is freed automatically
121
1/2
✓ Branch 0 taken 248 times.
✗ Branch 1 not taken.
248 if (x509_store_) X509_STORE_free(x509_store_);
122
123 248 EVP_cleanup();
124
125 248 private_key_ = NULL;
126 248 private_master_key_ = NULL;
127 248 certificate_ = NULL;
128 248 x509_store_ = NULL;
129 248 x509_lookup_ = NULL;
130 248 }
131
132
133 /**
134 * OpenSSL error strings.
135 */
136 string SignatureManager::GetCryptoError() {
137 char buf[121];
138 string err;
139 while (ERR_peek_error() != 0) {
140 ERR_error_string(ERR_get_error(), buf);
141 err += string(buf);
142 }
143 return err;
144 }
145
146
147 /**
148 * @param[in] file_pem File name of the PEM key file
149 * @param[in] password Password for the private key.
150 * Password is not saved internally, but the private key is.
151 * \return True on success, false otherwise
152 */
153 41 bool SignatureManager::LoadPrivateMasterKeyPath(const string &file_pem)
154 {
155 41 UnloadPrivateMasterKey();
156 FILE *fp;
157
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
41 if ((fp = fopen(file_pem.c_str(), "r")) == NULL)
158 return false;
159 41 private_master_key_ = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
160 41 fclose(fp);
161 41 return (private_master_key_ != NULL);
162 }
163
164 1 bool SignatureManager::LoadPrivateMasterKeyMem(const string &key)
165 {
166 1 UnloadPrivateMasterKey();
167 1 BIO *bp = BIO_new(BIO_s_mem());
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(bp != NULL);
169
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (BIO_write(bp, key.data(), key.size()) <= 0) {
170 BIO_free(bp);
171 return false;
172 }
173 1 private_master_key_ = PEM_read_bio_RSAPrivateKey(bp, NULL, NULL, NULL);
174 1 BIO_free(bp);
175 1 return (private_master_key_ != NULL);
176 }
177
178
179 /**
180 * @param[in] file_pem File name of the PEM key file
181 * @param[in] password Password for the private key.
182 * Password is not saved internally, but the private key is.
183 * \return True on success, false otherwise
184 */
185 115 bool SignatureManager::LoadPrivateKeyPath(const string &file_pem,
186 const string &password)
187 {
188 115 UnloadPrivateKey();
189 bool result;
190 115 FILE *fp = NULL;
191 115 char *tmp = strdupa(password.c_str());
192
193
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 115 times.
115 if ((fp = fopen(file_pem.c_str(), "r")) == NULL)
194 return false;
195 115 result = (private_key_ = PEM_read_PrivateKey(fp, NULL, NULL, tmp)) != NULL;
196 115 fclose(fp);
197 115 return result;
198 }
199
200 1 bool SignatureManager::LoadPrivateKeyMem(const std::string &key)
201 {
202 1 UnloadPrivateKey();
203 1 BIO *bp = BIO_new(BIO_s_mem());
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(bp != NULL);
205
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (BIO_write(bp, key.data(), key.size()) <= 0) {
206 BIO_free(bp);
207 return false;
208 }
209 1 private_key_ = PEM_read_bio_PrivateKey(bp, NULL, NULL, NULL);
210 1 BIO_free(bp);
211 1 return (private_key_ != NULL);
212 }
213
214
215 /**
216 * Clears the memory storing the private key.
217 */
218 372 void SignatureManager::UnloadPrivateKey() {
219
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 248 times.
372 if (private_key_) EVP_PKEY_free(private_key_);
220 372 private_key_ = NULL;
221 372 }
222
223
224 256 void SignatureManager::UnloadCertificate() {
225
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 109 times.
256 if (certificate_) X509_free(certificate_);
226 256 certificate_ = NULL;
227 256 }
228
229
230 /**
231 * Clears the memory storing the private RSA master key (whitelist signing).
232 */
233 298 void SignatureManager::UnloadPrivateMasterKey() {
234
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 248 times.
298 if (private_master_key_) RSA_free(private_master_key_);
235 298 private_master_key_ = NULL;
236 298 }
237
238
239 /**
240 * Loads a certificate. This certificate is used for the following
241 * signature verifications
242 *
243 * \return True on success, false otherwise
244 */
245 114 bool SignatureManager::LoadCertificatePath(const string &file_pem) {
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if (certificate_) {
247 X509_free(certificate_);
248 certificate_ = NULL;
249 }
250
251 bool result;
252 114 char *nopwd = strdupa("");
253 FILE *fp;
254
255
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
114 if ((fp = fopen(file_pem.c_str(), "r")) == NULL)
256 return false;
257 114 result = (certificate_ = PEM_read_X509_AUX(fp, NULL, NULL, nopwd)) != NULL;
258
259
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
114 if (!result && certificate_) {
260 X509_free(certificate_);
261 certificate_ = NULL;
262 }
263
264 114 fclose(fp);
265 114 return result;
266 }
267
268
269 /**
270 * See the function that loads the certificate from file.
271 */
272 33 bool SignatureManager::LoadCertificateMem(const unsigned char *buffer,
273 const unsigned buffer_size)
274 {
275
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 25 times.
33 if (certificate_) {
276 8 X509_free(certificate_);
277 8 certificate_ = NULL;
278 }
279
280 bool result;
281 33 char *nopwd = strdupa("");
282
283 33 BIO *mem = BIO_new(BIO_s_mem());
284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (!mem) return false;
285
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if (BIO_write(mem, buffer, buffer_size) <= 0) {
286 BIO_free(mem);
287 return false;
288 }
289 33 result = (certificate_ = PEM_read_bio_X509_AUX(mem, NULL, NULL, nopwd))
290 != NULL;
291 33 BIO_free(mem);
292
293
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
33 if (!result && certificate_) {
294 X509_free(certificate_);
295 certificate_ = NULL;
296 }
297
298 33 return result;
299 }
300
301
302 /**
303 * Loads a list of public RSA keys separated by ":".
304 */
305 126 bool SignatureManager::LoadPublicRsaKeys(const string &path_list) {
306
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 UnloadPublicRsaKeys();
307
308
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 102 times.
126 if (path_list == "")
309 24 return true;
310
1/2
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
102 const vector<string> pem_files = SplitString(path_list, ':');
311
312 102 char *nopwd = strdupa("");
313 FILE *fp;
314
315
2/2
✓ Branch 1 taken 102 times.
✓ Branch 2 taken 99 times.
201 for (unsigned i = 0; i < pem_files.size(); ++i) {
316 102 const char* pubkey_file = pem_files[i].c_str();
317
318 // open public key file
319
1/2
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
102 fp = fopen(pubkey_file, "r");
320
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 99 times.
102 if (fp == NULL) {
321
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 LogCvmfs(kLogSignature, kLogDebug | kLogSyslogErr, "failed to open "
322 "public key '%s'",
323 pubkey_file);
324 3 return false;
325 }
326
327 // load the public key from the file (and close it)
328
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 EVP_PKEY *this_key = PEM_read_PUBKEY(fp, NULL, NULL, nopwd);
329
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 fclose(fp);
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (this_key == NULL) {
331 LogCvmfs(kLogSignature, kLogDebug | kLogSyslogErr, "failed to load "
332 "public key '%s'",
333 pubkey_file);
334 return false;
335 }
336
337 // read the RSA key from the loaded public key
338
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 RSA *key = EVP_PKEY_get1_RSA(this_key);
339
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 EVP_PKEY_free(this_key);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (key == NULL) {
341 LogCvmfs(kLogSignature, kLogDebug | kLogSyslogErr, "failed to read "
342 "public key '%s'",
343 pubkey_file);
344 return false;
345 }
346
347 // store the loaded public key
348
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 public_keys_.push_back(key);
349 }
350
351 99 return true;
352 102 }
353
354
355 382 void SignatureManager::UnloadPublicRsaKeys() {
356
2/2
✓ Branch 1 taken 107 times.
✓ Branch 2 taken 382 times.
489 for (unsigned i = 0; i < public_keys_.size(); ++i)
357 107 RSA_free(public_keys_[i]);
358 382 public_keys_.clear();
359 382 }
360
361
362 1 std::string SignatureManager::GenerateKeyText(RSA *pubkey) const {
363
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (!pubkey) {return "";}
364
365
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 BIO *bp = BIO_new(BIO_s_mem());
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (bp == NULL) {
367 LogCvmfs(kLogSignature, kLogDebug | kLogSyslogErr, "Failed to allocate"
368 " memory for pubkey");
369 return "";
370 }
371
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (!PEM_write_bio_RSA_PUBKEY(bp, pubkey)) {
372 LogCvmfs(kLogSignature, kLogDebug | kLogSyslogErr, "Failed to write"
373 " pubkey to memory");
374 return "";
375 }
376 char *bio_pubkey_text;
377
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 long bytes = BIO_get_mem_data(bp, &bio_pubkey_text); // NOLINT
378
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 std::string bio_pubkey_str(bio_pubkey_text, bytes);
379
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 BIO_free(bp);
380
381 1 return bio_pubkey_str;
382 1 }
383
384
385 1 std::string SignatureManager::GetActivePubkeys() const {
386 1 std::string pubkeys;
387 1 for (std::vector<RSA *>::const_iterator it = public_keys_.begin();
388
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 it != public_keys_.end();
389 1 it++) {
390
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 pubkeys += GenerateKeyText(*it);
391 }
392 // NOTE: we do not add the pubkey of the certificate here, as it is
393 // not used for the whitelist verification.
394 1 return pubkeys;
395 }
396
397 std::vector<std::string> SignatureManager::GetActivePubkeysAsVector() const {
398 std::vector<std::string> pubkeys;
399 for (std::vector<RSA *>::const_iterator it = public_keys_.begin();
400 it != public_keys_.end();
401 it++) {
402 pubkeys.push_back(GenerateKeyText(*it));
403 }
404 // NOTE: we do not add the pubkey of the certificate here, as it is
405 // not used for the whitelist verification.
406 return pubkeys;
407 }
408
409 2 std::string SignatureManager::GetCertificate() const {
410
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 if (!certificate_) return "";
411
412
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 BIO *bp = BIO_new(BIO_s_mem());
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(bp != NULL);
414
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 bool rvb = PEM_write_bio_X509(bp, certificate_);
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(rvb);
416 char *bio_crt_text;
417
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 long bytes = BIO_get_mem_data(bp, &bio_crt_text); // NOLINT
418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(bytes > 0);
419
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::string bio_crt_str(bio_crt_text, bytes);
420
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 BIO_free(bp);
421 2 return bio_crt_str;
422 2 }
423
424
425 2 std::string SignatureManager::GetPrivateKey() {
426
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 if (!private_key_) return "";
427
428
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 BIO *bp = BIO_new(BIO_s_mem());
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(bp != NULL);
430
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 bool rvb = PEM_write_bio_PrivateKey(bp, private_key_, NULL, NULL, 0, 0, NULL);
431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(rvb);
432 char *bio_privkey_text;
433
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 long bytes = BIO_get_mem_data(bp, &bio_privkey_text); // NOLINT
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(bytes > 0);
435
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::string bio_privkey_str(bio_privkey_text, bytes);
436
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 BIO_free(bp);
437 2 return bio_privkey_str;
438 2 }
439
440
441 2 std::string SignatureManager::GetPrivateMasterKey() {
442
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 if (!private_master_key_) return "";
443
444
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 BIO *bp = BIO_new(BIO_s_mem());
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(bp != NULL);
446
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 bool rvb = PEM_write_bio_RSAPrivateKey(bp, private_master_key_,
447 2 NULL, NULL, 0, 0, NULL);
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(rvb);
449 char *bio_master_privkey_text;
450
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 long bytes = BIO_get_mem_data(bp, &bio_master_privkey_text); // NOLINT
451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(bytes > 0);
452
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::string bio_master_privkey_str(bio_master_privkey_text, bytes);
453
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 BIO_free(bp);
454 2 return bio_master_privkey_str;
455 2 }
456
457 16 RSA *SignatureManager::GenerateRsaKeyPair() {
458 16 RSA *rsa = NULL;
459 16 BIGNUM *bn = BN_new();
460 16 int retval = BN_set_word(bn, RSA_F4);
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 assert(retval == 1);
462 #ifdef OPENSSL_API_INTERFACE_V09
463 rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
464 assert(rsa != NULL);
465 #else
466 16 rsa = RSA_new();
467 16 retval = RSA_generate_key_ex(rsa, 2048, bn, NULL);
468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 assert(retval == 1);
469 #endif
470 16 BN_free(bn);
471 16 return rsa;
472 }
473
474
475 /**
476 * Creates the RSA master key pair for whitelist signing
477 */
478 8 void SignatureManager::GenerateMasterKeyPair() {
479 8 UnloadPrivateMasterKey();
480 8 UnloadPublicRsaKeys();
481
482 8 RSA *rsa = GenerateRsaKeyPair();
483 8 private_master_key_ = RSAPrivateKey_dup(rsa);
484
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 public_keys_.push_back(RSAPublicKey_dup(rsa));
485 8 RSA_free(rsa);
486 8 }
487
488 /**
489 * Creates a new RSA key pair (private key) and a self-signed certificate
490 */
491 8 void SignatureManager::GenerateCertificate(const std::string &cn) {
492
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 UnloadPrivateKey();
493
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 UnloadCertificate();
494 int retval;
495
496
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 RSA *rsa = GenerateRsaKeyPair();
497
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 private_key_ = EVP_PKEY_new();
498
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 retval = EVP_PKEY_set1_RSA(private_key_, RSAPrivateKey_dup(rsa));
499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assert(retval == 1);
500
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 EVP_PKEY *pkey = EVP_PKEY_new();
501
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 retval = EVP_PKEY_set1_RSA(pkey, rsa);
502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assert(retval == 1);
503
504
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 certificate_ = X509_new();
505
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_set_version(certificate_, 2L);
506
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_set_pubkey(certificate_, pkey);
507
508 8 Prng prng;
509 8 prng.InitLocaltime();
510 8 unsigned long rnd_serial_no = prng.Next(uint64_t(1) + uint32_t(-1)); //NOLINT
511 8 rnd_serial_no = rnd_serial_no |
512 8 uint64_t(prng.Next(uint64_t(1) + uint32_t(-1))) << 32;
513
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 ASN1_INTEGER_set(X509_get_serialNumber(certificate_), rnd_serial_no);
514
515 // valid as of now
516
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_gmtime_adj(reinterpret_cast<ASN1_TIME *>(
517
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_get_notBefore(certificate_)), 0);
518 // valid for 1 year (validity range is unused)
519
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_gmtime_adj(reinterpret_cast<ASN1_TIME *>(
520
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_get_notAfter(certificate_)), 3600 * 24 * 365);
521
522
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_NAME *name = X509_get_subject_name(certificate_);
523 #ifdef OPENSSL_API_INTERFACE_V09
524 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
525 const_cast<unsigned char *>(
526 reinterpret_cast<const unsigned char *>(cn.c_str())),
527 -1, -1, 0);
528 #else
529
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
530 8 reinterpret_cast<const unsigned char *>(cn.c_str()), -1, -1, 0);
531 #endif
532
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 retval = X509_set_issuer_name(certificate_, name);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assert(retval == 1);
534
535 #ifdef OPENSSL_API_INTERFACE_V09
536 retval = X509_sign(certificate_, pkey, EVP_sha1());
537 #else
538
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 retval = X509_sign(certificate_, pkey, EVP_sha256());
539 #endif
540
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 EVP_PKEY_free(pkey);
541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assert(retval > 0);
542 8 }
543
544 /**
545 * Loads a list of blacklisted certificates (fingerprints) from a file.
546 */
547 3 bool SignatureManager::LoadBlacklist(
548 const std::string &path_blacklist,
549 bool append)
550 {
551 3 MutexLockGuard lock_guard(&lock_blacklist_);
552
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 LogCvmfs(kLogSignature, kLogDebug, "reading from blacklist %s",
553 path_blacklist.c_str());
554
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!append)
555 3 blacklist_.clear();
556
557
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 int fd = open(path_blacklist.c_str(), O_RDONLY);
558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (fd < 0)
559 return false;
560 3 std::string blacklist_buffer;
561
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 bool retval = SafeReadToString(fd, &blacklist_buffer);
562
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 close(fd);
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!retval)
564 return false;
565
566 3 unsigned num_bytes = 0;
567
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 while (num_bytes < blacklist_buffer.size()) {
568 6 const string line = GetLineMem(blacklist_buffer.data() + num_bytes,
569
1/2
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
3 blacklist_buffer.size() - num_bytes);
570
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 blacklist_.push_back(line);
571 3 num_bytes += line.length() + 1;
572 3 }
573
574 3 return true;
575 3 }
576
577
578 92 vector<string> SignatureManager::GetBlacklist() {
579 92 MutexLockGuard lock_guard(&lock_blacklist_);
580
1/2
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
184 return blacklist_;
581 92 }
582
583
584 /**
585 * Loads CA certificates CRLs from a ":" separated list of paths.
586 * The information is used for proper X509 verification.
587 * The format of the certificates and CRLs has to be OpenSSL hashed certs.
588 * The path can be something like /etc/grid-security/certificates.
589 * If path_list is empty, the default path is taken.
590 */
591 bool SignatureManager::LoadTrustedCaCrl(const string &path_list) {
592 InitX509Store();
593
594 /* TODO if (path_list == "") {
595 return true;
596 }*/
597 const vector<string> paths = SplitString(path_list, ':');
598 for (unsigned i = 0; i < paths.size(); ++i) {
599 int retval = X509_LOOKUP_add_dir(x509_lookup_, paths[i].c_str(),
600 X509_FILETYPE_PEM);
601 if (!retval)
602 return false;
603 }
604 return true;
605 }
606
607
608 /**
609 * Returns cryptographic hash from DER encoded certificate, encoded the same way
610 * OpenSSL does (01:AB:...).
611 * Empty string on failure.
612 */
613 66 shash::Any SignatureManager::HashCertificate(
614 const shash::Algorithms hash_algorithm)
615 {
616
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 shash::Any result;
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (!certificate_)
618 return result;
619
620 int buffer_size;
621 66 unsigned char *buffer = NULL;
622
623
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 buffer_size = i2d_X509(certificate_, &buffer);
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (buffer_size < 0)
625 return result;
626
627 66 result.algorithm = hash_algorithm;
628
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 shash::HashMem(buffer, buffer_size, &result);
629 66 free(buffer);
630
631 66 return result;
632 }
633
634
635 /**
636 * Returns cryptographic hash from DER encoded certificate, encoded the same way
637 * OpenSSL does (01:AB:...).
638 * Empty string on failure.
639 */
640 35 string SignatureManager::FingerprintCertificate(
641 const shash::Algorithms hash_algorithm)
642 {
643
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 shash::Any hash = HashCertificate(hash_algorithm);
644
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
35 if (hash.IsNull())
645 return "";
646
647
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 const string hash_str = hash.ToString();
648 35 string result;
649
2/2
✓ Branch 1 taken 1535 times.
✓ Branch 2 taken 35 times.
1570 for (unsigned i = 0; i < hash_str.length(); ++i) {
650
2/2
✓ Branch 0 taken 1400 times.
✓ Branch 1 taken 135 times.
1535 if (i < 2*shash::kDigestSizes[hash_algorithm]) {
651
5/6
✓ Branch 0 taken 1365 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 665 times.
✓ Branch 3 taken 700 times.
✓ Branch 5 taken 665 times.
✗ Branch 6 not taken.
1400 if ((i > 0) && (i%2 == 0)) result += ":";
652 }
653
1/2
✓ Branch 2 taken 1535 times.
✗ Branch 3 not taken.
1535 result += toupper(hash_str[i]);
654 }
655 35 return result;
656 35 }
657
658
659 /**
660 * Parses a fingerprint from the whitelist
661 */
662 49 shash::Any SignatureManager::MkFromFingerprint(const std::string &fingerprint) {
663 49 string convert;
664
2/2
✓ Branch 1 taken 2641 times.
✓ Branch 2 taken 48 times.
2689 for (unsigned i = 0; i < fingerprint.length(); ++i) {
665
5/6
✓ Branch 1 taken 2640 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 2640 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2640 times.
5281 if ((fingerprint[i] == ' ') || (fingerprint[i] == '\t') ||
666
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2640 times.
2640 (fingerprint[i] == '#'))
667 {
668 1 break;
669 }
670
2/2
✓ Branch 1 taken 1823 times.
✓ Branch 2 taken 817 times.
2640 if (fingerprint[i] != ':')
671
1/2
✓ Branch 2 taken 1823 times.
✗ Branch 3 not taken.
1823 convert.push_back(tolower(fingerprint[i]));
672 }
673
674
1/2
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
98 return shash::MkFromHexPtr(shash::HexPtr(convert));
675 49 }
676
677
678 /**
679 * \return Some human-readable information about the loaded certificate.
680 */
681 string SignatureManager::Whois() {
682 if (!certificate_) return "No certificate loaded";
683
684 string result;
685 X509_NAME *subject = X509_get_subject_name(certificate_);
686 X509_NAME *issuer = X509_get_issuer_name(certificate_);
687 char *buffer = NULL;
688 buffer = X509_NAME_oneline(subject, NULL, 0);
689 if (buffer) {
690 result = "Publisher: " + string(buffer);
691 free(buffer);
692 }
693 buffer = X509_NAME_oneline(issuer, NULL, 0);
694 if (buffer) {
695 result += "\nCertificate issued by: " + string(buffer);
696 free(buffer);
697 }
698 return result;
699 }
700
701
702 bool SignatureManager::WriteCertificateMem(unsigned char **buffer,
703 unsigned *buffer_size)
704 {
705 BIO *mem = BIO_new(BIO_s_mem());
706 if (!mem) return false;
707 if (!PEM_write_bio_X509(mem, certificate_)) {
708 BIO_free(mem);
709 return false;
710 }
711
712 void *bio_buffer;
713 *buffer_size = BIO_get_mem_data(mem, &bio_buffer);
714 *buffer = reinterpret_cast<unsigned char *>(smalloc(*buffer_size));
715 memcpy(*buffer, bio_buffer, *buffer_size);
716 BIO_free(mem);
717 return true;
718 }
719
720
721 /**
722 * Checks, whether the loaded certificate and the loaded private key match.
723 *
724 * \return True, if private key and certificate match, false otherwise.
725 */
726 78 bool SignatureManager::KeysMatch() {
727
2/4
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
78 if (!certificate_ || !private_key_)
728 return false;
729
730 78 bool result = false;
731 78 const unsigned char *sign_me = reinterpret_cast<const unsigned char *>
732 ("sign me");
733 78 unsigned char *signature = NULL;
734 unsigned signature_size;
735
3/6
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
✗ Branch 6 not taken.
156 if (Sign(sign_me, 7, &signature, &signature_size) &&
736
2/4
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
78 Verify(sign_me, 7, signature, signature_size))
737 {
738 78 result = true;
739 }
740
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 if (signature) free(signature);
741 78 return result;
742 }
743
744
745 /**
746 * Verifies the currently loaded certificate against the trusted CA chain.
747 */
748 bool SignatureManager::VerifyCaChain() {
749 if (!certificate_)
750 return false;
751
752 X509_STORE_CTX *csc = NULL;
753 csc = X509_STORE_CTX_new();
754 assert(csc);
755
756 X509_STORE_CTX_init(csc, x509_store_, certificate_, NULL);
757 bool result = X509_verify_cert(csc) == 1;
758 X509_STORE_CTX_free(csc);
759
760 return result;
761 }
762
763
764 /**
765 * Signs a data block using the loaded private key.
766 *
767 * \return True on success, false otherwise
768 */
769 175 bool SignatureManager::Sign(const unsigned char *buffer,
770 const unsigned buffer_size,
771 unsigned char **signature,
772 unsigned *signature_size)
773 {
774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 175 times.
175 if (!private_key_) {
775 *signature_size = 0;
776 *signature = NULL;
777 return false;
778 }
779
780 175 bool result = false;
781 #ifdef OPENSSL_API_INTERFACE_V11
782 175 EVP_MD_CTX *ctx_ptr = EVP_MD_CTX_new();
783 #else
784 EVP_MD_CTX ctx;
785 EVP_MD_CTX_init(&ctx);
786 EVP_MD_CTX *ctx_ptr = &ctx;
787 #endif
788
789 175 *signature = reinterpret_cast<unsigned char *>(
790 175 smalloc(EVP_PKEY_size(private_key_)));
791 175 if (EVP_SignInit(ctx_ptr, EVP_sha1()) &&
792
3/6
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 175 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 175 times.
✗ Branch 6 not taken.
350 EVP_SignUpdate(ctx_ptr, buffer, buffer_size) &&
793
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
175 EVP_SignFinal(ctx_ptr, *signature, signature_size, private_key_))
794 {
795 175 result = true;
796 }
797 #ifdef OPENSSL_API_INTERFACE_V11
798 175 EVP_MD_CTX_free(ctx_ptr);
799 #else
800 EVP_MD_CTX_cleanup(&ctx);
801 #endif
802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 175 times.
175 if (!result) {
803 free(*signature);
804 *signature_size = 0;
805 *signature = NULL;
806 }
807
808 175 return result;
809 }
810
811
812 /**
813 * Signs a data block using the loaded private master key.
814 *
815 * \return True on success, false otherwise
816 */
817 39 bool SignatureManager::SignRsa(const unsigned char *buffer,
818 const unsigned buffer_size,
819 unsigned char **signature,
820 unsigned *signature_size)
821 {
822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (!private_master_key_) {
823 *signature_size = 0;
824 *signature = NULL;
825 return false;
826 }
827
828 39 unsigned char *to = (unsigned char *)smalloc(RSA_size(private_master_key_));
829 39 unsigned char *from = (unsigned char *)smalloc(buffer_size);
830 39 memcpy(from, buffer, buffer_size);
831
832 39 int size = RSA_private_encrypt(buffer_size, from, to,
833 private_master_key_, RSA_PKCS1_PADDING);
834 39 free(from);
835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (size < 0) {
836 *signature_size = 0;
837 *signature = NULL;
838 return false;
839 }
840 39 *signature = to;
841 39 *signature_size = size;
842 39 return true;
843 }
844
845
846 /**
847 * Verifies a signature against loaded certificate.
848 *
849 * \return True if signature is valid, false on error or otherwise
850 */
851 112 bool SignatureManager::Verify(const unsigned char *buffer,
852 const unsigned buffer_size,
853 const unsigned char *signature,
854 const unsigned signature_size)
855 {
856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (!certificate_) return false;
857
858 112 bool result = false;
859 #ifdef OPENSSL_API_INTERFACE_V11
860 112 EVP_MD_CTX *ctx_ptr = EVP_MD_CTX_new();
861 #else
862 EVP_MD_CTX ctx;
863 EVP_MD_CTX_init(&ctx);
864 EVP_MD_CTX *ctx_ptr = &ctx;
865 #endif
866
867 112 EVP_PKEY *pubkey = X509_get_pubkey(certificate_);
868 112 if (EVP_VerifyInit(ctx_ptr, EVP_sha1()) &&
869
3/6
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 112 times.
✗ Branch 6 not taken.
224 EVP_VerifyUpdate(ctx_ptr, buffer, buffer_size) &&
870 #ifdef OPENSSL_API_INTERFACE_V09
871 EVP_VerifyFinal(ctx_ptr,
872 const_cast<unsigned char *>(signature), signature_size,
873 pubkey)
874 #else
875
1/2
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
112 EVP_VerifyFinal(ctx_ptr, signature, signature_size, pubkey)
876 #endif
877 )
878 {
879 112 result = true;
880 }
881
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 if (pubkey != NULL)
882 112 EVP_PKEY_free(pubkey);
883 #ifdef OPENSSL_API_INTERFACE_V11
884 112 EVP_MD_CTX_free(ctx_ptr);
885 #else
886 EVP_MD_CTX_cleanup(&ctx);
887 #endif
888
889 112 return result;
890 }
891
892
893 /**
894 * Verifies a signature against all loaded public keys.
895 *
896 * \return True if signature is valid with any public key, false on error or otherwise
897 */
898 45 bool SignatureManager::VerifyRsa(const unsigned char *buffer,
899 const unsigned buffer_size,
900 const unsigned char *signature,
901 const unsigned signature_size)
902 {
903
1/2
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
45 for (unsigned i = 0, s = public_keys_.size(); i < s; ++i) {
904
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
45 if (buffer_size > (unsigned)RSA_size(public_keys_[i]))
905 continue;
906
907 45 unsigned char *to = (unsigned char *)smalloc(RSA_size(public_keys_[i]));
908 45 unsigned char *from = (unsigned char *)smalloc(signature_size);
909 45 memcpy(from, signature, signature_size);
910
911 45 int size = RSA_public_decrypt(signature_size, from, to,
912 45 public_keys_[i], RSA_PKCS1_PADDING);
913 45 free(from);
914
2/4
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
45 if ((size >= 0) && (unsigned(size) == buffer_size) &&
915
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 (memcmp(buffer, to, size) == 0))
916 {
917 45 free(to);
918 45 return true;
919 }
920
921 free(to);
922 }
923
924 LogCvmfs(kLogSignature, kLogDebug, "VerifyRsa, no public key fits");
925 return false;
926 }
927
928
929 /**
930 * Strips a signature from the letter (if exists)
931 */
932 72 void SignatureManager::CutLetter(const unsigned char *buffer,
933 const unsigned buffer_size,
934 const char separator,
935 unsigned *letter_length,
936 unsigned *pos_after_mark)
937 {
938 72 unsigned pos = 0;
939 72 *letter_length = *pos_after_mark = 0;
940 do {
941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10772 times.
10772 if (pos == buffer_size) {
942 *pos_after_mark = pos; // Careful: pos_after_mark points out of buffer
943 *letter_length = pos;
944 break;
945 }
946
947
3/4
✓ Branch 0 taken 498 times.
✓ Branch 1 taken 10274 times.
✓ Branch 2 taken 498 times.
✗ Branch 3 not taken.
10772 if ((buffer[pos] == '\n') && (pos+4 <= buffer_size) &&
948
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 426 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
498 (buffer[pos+1] == separator) && (buffer[pos+2] == separator) &&
949
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 (buffer[pos+3] == '\n'))
950 {
951 72 *letter_length = pos+1;
952 72 pos += 4;
953 72 break;
954 }
955 10700 pos++;
956 } while (true);
957 72 *pos_after_mark = pos;
958 72 }
959
960
961 /**
962 * Checks a document of the form
963 * <ASCII LINES>
964 * --
965 * <hash>
966 * <signature>
967 */
968 72 bool SignatureManager::VerifyLetter(const unsigned char *buffer,
969 const unsigned buffer_size,
970 const bool by_rsa)
971 {
972 72 unsigned pos = 0;
973 72 unsigned letter_length = 0;
974
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 CutLetter(buffer, buffer_size, '-', &letter_length, &pos);
975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pos >= buffer_size)
976 return false;
977
978
1/2
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
72 string hash_str = "";
979 72 unsigned hash_pos = pos;
980 do {
981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
3042 if (pos == buffer_size)
982 return false;
983
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 2970 times.
3042 if (buffer[pos] == '\n') {
984 72 pos++;
985 72 break;
986 }
987
1/2
✓ Branch 1 taken 2970 times.
✗ Branch 2 not taken.
2970 hash_str.push_back(buffer[pos++]);
988 } while (true);
989
1/2
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
72 shash::Any hash_printed = shash::MkFromHexPtr(shash::HexPtr(hash_str));
990
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 shash::Any hash_computed(hash_printed.algorithm);
991
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 shash::HashMem(buffer, letter_length, &hash_computed);
992
2/4
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 72 times.
72 if (hash_printed != hash_computed)
993 return false;
994
995
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 31 times.
72 if (by_rsa) {
996
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
41 return VerifyRsa(&buffer[hash_pos], hash_str.length(),
997 82 &buffer[pos], buffer_size-pos);
998 } else {
999
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 return Verify(&buffer[hash_pos], hash_str.length(),
1000 62 &buffer[pos], buffer_size-pos);
1001 }
1002 72 }
1003
1004
1005 /**
1006 * Verifies a PKCS#7 binary content + signature structure
1007 * using the loaded trusted CAs/CRLs
1008 */
1009 bool SignatureManager::VerifyPkcs7(const unsigned char *buffer,
1010 const unsigned buffer_size,
1011 unsigned char **content,
1012 unsigned *content_size,
1013 vector<string> *alt_uris)
1014 {
1015 *content = NULL;
1016 *content_size = 0;
1017
1018 BIO *bp_pkcs7 = BIO_new(BIO_s_mem());
1019 if (!bp_pkcs7) return false;
1020 if (BIO_write(bp_pkcs7, buffer, buffer_size) <= 0) {
1021 BIO_free(bp_pkcs7);
1022 return false;
1023 }
1024
1025 PKCS7 *pkcs7 = NULL;
1026 pkcs7 = PEM_read_bio_PKCS7(bp_pkcs7, NULL, NULL, NULL);
1027 BIO_free(bp_pkcs7);
1028 if (!pkcs7) {
1029 LogCvmfs(kLogSignature, kLogDebug, "invalid pkcs#7 signature");
1030 return false;
1031 }
1032
1033 BIO *bp_content = BIO_new(BIO_s_mem());
1034 if (!bp_content) {
1035 PKCS7_free(pkcs7);
1036 return false;
1037 }
1038
1039 int flags = 0;
1040 STACK_OF(X509) *extra_signers = NULL;
1041 BIO *indata = NULL;
1042 bool result = PKCS7_verify(pkcs7, extra_signers, x509_store_, indata,
1043 bp_content, flags);
1044 if (result != 1) {
1045 BIO_free(bp_content);
1046 PKCS7_free(pkcs7);
1047 return false;
1048 }
1049
1050 BUF_MEM *bufmem_content;
1051 BIO_get_mem_ptr(bp_content, &bufmem_content);
1052 // BIO_free() leaves BUF_MEM alone
1053 (void) BIO_set_close(bp_content, BIO_NOCLOSE);
1054 BIO_free(bp_content);
1055 *content = reinterpret_cast<unsigned char *>(bufmem_content->data);
1056 *content_size = bufmem_content->length;
1057 free(bufmem_content);
1058 if (*content == NULL) {
1059 PKCS7_free(pkcs7);
1060 LogCvmfs(kLogSignature, kLogDebug, "empty pkcs#7 structure");
1061 return false;
1062 }
1063
1064 // Extract signing certificates
1065 STACK_OF(X509) *signers = NULL;
1066 signers = PKCS7_get0_signers(pkcs7, NULL, 0);
1067 assert(signers);
1068
1069 // Extract alternative names
1070 for (int i = 0; i < sk_X509_num(signers); ++i) {
1071 X509* this_signer = sk_X509_value(signers, i);
1072 GENERAL_NAMES *subject_alt_names = NULL;
1073 subject_alt_names = reinterpret_cast<GENERAL_NAMES *>(
1074 X509_get_ext_d2i(this_signer, NID_subject_alt_name, NULL, NULL));
1075 if (subject_alt_names != NULL) {
1076 for (int j = 0; j < sk_GENERAL_NAME_num(subject_alt_names); ++j) {
1077 GENERAL_NAME *this_name = sk_GENERAL_NAME_value(subject_alt_names, j);
1078 if (this_name->type != GEN_URI)
1079 continue;
1080
1081 const char *name_ptr = reinterpret_cast<const char *>(
1082 #ifdef OPENSSL_API_INTERFACE_V11
1083 ASN1_STRING_get0_data(this_name->d.uniformResourceIdentifier));
1084 #else
1085 ASN1_STRING_data(this_name->d.uniformResourceIdentifier));
1086 #endif
1087 int name_len =
1088 ASN1_STRING_length(this_name->d.uniformResourceIdentifier);
1089 if (!name_ptr || (name_len <= 0))
1090 continue;
1091 alt_uris->push_back(string(name_ptr, name_len));
1092 }
1093 }
1094 }
1095 sk_X509_free(signers);
1096 PKCS7_free(pkcs7);
1097 return true;
1098 }
1099
1100 } // namespace signature
1101