GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/letter.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 0 79 0.0%
Branches: 0 30 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "cvmfs_config.h"
6 #include "letter.h"
7
8 #include <inttypes.h>
9 #include <cassert>
10
11 #include <map>
12
13 #include "crypto/signature.h"
14 #include "util/string.h"
15
16 using namespace std; // NOLINT
17
18 namespace letter {
19
20 Letter::Letter(const string &fqrn,
21 const string &text,
22 signature::SignatureManager *signature_manager) :
23 fqrn_(fqrn),
24 text_(text),
25 signature_manager_(signature_manager)
26 {
27 }
28
29
30 string Letter::Sign(const shash::Algorithms hash_algorithm) {
31 unsigned char *cert_buf = NULL;
32 unsigned cert_buf_size;
33 bool retval = signature_manager_->WriteCertificateMem(&cert_buf,
34 &cert_buf_size);
35 assert(retval);
36 string cert_base64 = Base64(string(reinterpret_cast<char *>(cert_buf),
37 cert_buf_size));
38 free(cert_buf);
39
40 string output = text_;
41 output += string("\n##\n") +
42 "V1" + "\n" +
43 "N" + fqrn_ + "\n" +
44 "T" + StringifyInt(time(NULL)) + "\n" +
45 "X" + cert_base64 + "\n";
46 shash::Any output_hash(hash_algorithm);
47 shash::HashMem(reinterpret_cast<const unsigned char *>(output.data()),
48 output.length(), &output_hash);
49 output += "--\n" + output_hash.ToString() + "\n";
50
51 unsigned char *sig;
52 unsigned sig_size;
53 retval = signature_manager_->Sign(
54 reinterpret_cast<const unsigned char *>(output_hash.ToString().data()),
55 output_hash.GetHexSize(), &sig, &sig_size);
56 assert(retval);
57 output.append(reinterpret_cast<char *>(sig), sig_size);
58 free(sig);
59
60 return Base64(output);
61 }
62
63
64 Failures Letter::Verify(uint64_t max_age, string *msg, string *cert) {
65 msg->clear();
66 cert->clear();
67 bool retval;
68
69 string dec;
70 retval = Debase64(text_, &dec);
71
72 if (!retval)
73 return kFailBadBase64;
74
75 // Cut envelope and signature
76 unsigned env_pos = 0;
77 unsigned sig_pos = 0;
78 unsigned msg_len = 0;
79 unsigned env_len = 0;
80 const unsigned char *data_ptr =
81 reinterpret_cast<const unsigned char *>(dec.data());
82 signature::SignatureManager::CutLetter(
83 data_ptr, dec.length(), '#', &msg_len, &env_pos);
84 if (env_pos >= dec.length())
85 return kFailMalformed;
86 // Sign adds a newline
87 if (msg_len == 0)
88 return kFailMalformed;
89 *msg = dec.substr(0, msg_len-1);
90 signature::SignatureManager::CutLetter(
91 data_ptr+env_pos, dec.length()-env_pos, '-', &env_len, &sig_pos);
92 if (sig_pos >= dec.length())
93 return kFailMalformed;
94
95 map<char, string> env;
96 ParseKeyvalMem(data_ptr+env_pos, env_len, &env);
97 map<char, string>::const_iterator iter;
98 if ((iter = env.find('T')) == env.end())
99 return kFailMalformed;
100 uint64_t timestamp = String2Uint64(iter->second);
101 if (max_age > 0) {
102 if (timestamp + max_age < static_cast<uint64_t>(time(NULL)))
103 return kFailExpired;
104 }
105 if ((iter = env.find('N')) == env.end())
106 return kFailMalformed;
107 if (iter->second != fqrn_)
108 return kFailNameMismatch;
109 if ((iter = env.find('X')) == env.end())
110 return kFailMalformed;
111 string cert_b64 = iter->second;
112 retval = Debase64(cert_b64, cert);
113 if (!retval)
114 return kFailMalformed;
115 retval = signature_manager_->LoadCertificateMem(
116 reinterpret_cast<const unsigned char *>(cert->data()), cert->length());
117 if (!retval)
118 return kFailBadCertificate;
119
120 retval = signature_manager_->VerifyLetter(
121 data_ptr, dec.length(), false);
122 if (!retval)
123 return kFailBadSignature;
124
125 return kFailOk;
126 }
127
128 } // namespace letter
129