monotone

Review 1: Make monotone compile against botan 1.10.1.

Created:2011-09-07 19:44:31 (13 years 3 months ago)
Updated:11 years 1 month ago
Author:Martin von Gagern
Commit:7cbb20501714be7f25f30734da82d41c7ac427ca
Description:Make monotone compile against botan 1.10.1.

This should fix the compile time errors occurring when building against botan starting with version 1.9.11. It addresses issue 182.
Reviewers:No reviewers at the moment.
Files: src/database.cc (2 diffs)
src/packet.cc (1 diff)
src/key_store.cc (2 diffs)
src/sha1.cc (1 diff)
src/ssh_agent.cc (1 diff)
src/gzip.cc (6 diffs)
src/gzip.hh (3 diffs)
src/key_packet.cc (1 diff)
 Archive Download the corresponding diff file
src/database.cc
OldNew
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
...
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
imp->execute(query("DELETE FROM public_keys WHERE id = ?")
% blob(pub_id.inner()()));
}
void
database::encrypt_rsa(key_id const & pub_id,
string const & plaintext,
rsa_oaep_sha_data & ciphertext)
{
MM(pub_id);
rsa_pub_key pub;
get_key(pub_id, pub);
SecureVector<Botan::byte> pub_block;
pub_block.set(reinterpret_cast<Botan::byte const *>(pub().data()),
pub().size());
shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key
= shared_dynamic_cast<RSA_PublicKey>(x509_key);
if (!pub_key)
throw recoverable_failure(origin::system,
"Failed to get RSA encrypting key");
shared_ptr<PK_Encryptor>
encryptor(get_pk_encryptor(*pub_key, "EME1(SHA-1)"));
SecureVector<Botan::byte> ct;
rsa_sha1_signature const & signature)
{
MM(id);
MM(alleged_text);
shared_ptr<PK_Verifier> verifier;
verifier_cache::const_iterator i = imp->verifiers.find(id);
if (i != imp->verifiers.end())
verifier = i->second.first;
else
{
rsa_pub_key pub;
SecureVector<Botan::byte> pub_block;
if (!public_key_exists(id))
return cert_unknown;
get_key(id, pub);
pub_block.set(reinterpret_cast<Botan::byte const *>(pub().data()),
pub().size());
L(FL("building verifier for %d-byte pub key") % pub_block.size());
shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key
= boost::shared_dynamic_cast<RSA_PublicKey>(x509_key);
E(pub_key, id.inner().made_from,
F("failed to get RSA verifying key for %s") % id);
verifier.reset(get_pk_verifier(*pub_key, "EMSA3(SHA-1)"));
/* XXX This is ugly. We need to keep the key around
* as long as the verifier is around, but the shared_ptr will go
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
...
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
imp->execute(query("DELETE FROM public_keys WHERE id = ?")
% blob(pub_id.inner()()));
}
void
database::encrypt_rsa(key_id const & pub_id,
string const & plaintext,
rsa_oaep_sha_data & ciphertext)
{
MM(pub_id);
rsa_pub_key pub;
get_key(pub_id, pub);
SecureVector<Botan::byte> pub_block
(reinterpret_cast<Botan::byte const *>(pub().data()), pub().size());
shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key
= shared_dynamic_cast<RSA_PublicKey>(x509_key);
if (!pub_key)
throw recoverable_failure(origin::system,
"Failed to get RSA encrypting key");
shared_ptr<PK_Encryptor>
encryptor(get_pk_encryptor(*pub_key, "EME1(SHA-1)"));
SecureVector<Botan::byte> ct;
rsa_sha1_signature const & signature)
{
MM(id);
MM(alleged_text);
shared_ptr<PK_Verifier> verifier;
verifier_cache::const_iterator i = imp->verifiers.find(id);
if (i != imp->verifiers.end())
verifier = i->second.first;
else
{
rsa_pub_key pub;
if (!public_key_exists(id))
return cert_unknown;
get_key(id, pub);
SecureVector<Botan::byte> pub_block
(reinterpret_cast<Botan::byte const *>(pub().data()), pub().size());
L(FL("building verifier for %d-byte pub key") % pub_block.size());
shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key
= boost::shared_dynamic_cast<RSA_PublicKey>(x509_key);
E(pub_key, id.inner().made_from,
F("failed to get RSA verifying key for %s") % id);
verifier.reset(get_pk_verifier(*pub_key, "EMSA3(SHA-1)"));
/* XXX This is ugly. We need to keep the key around
* as long as the verifier is around, but the shared_ptr will go
src/packet.cc
OldNew
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
made_from,
F("malformed packet: invalid base64 block"));
}
void validate_key(string const & k) const
{
E(!k.empty()
&& k.find_first_not_of(constants::legal_key_name_bytes) == string::npos,
made_from,
F("malformed packet: invalid key name"));
}
void validate_public_key_data(string const & name, string const & keydata) const
{
string decoded = decode_base64_as<string>(keydata, origin::user);
Botan::SecureVector<Botan::byte> key_block;
key_block.set(reinterpret_cast<Botan::byte const *>(decoded.c_str()), decoded.size());
try
{
Botan::X509::load_key(key_block);
}
catch (Botan::Decoding_Error const & e)
{
E(false, origin::user,
F("malformed packet: invalid public key data for '%s': %s")
% name % e.what());
}
}
void validate_private_key_data(string const & name, string const & keydata) const
{
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
made_from,
F("malformed packet: invalid base64 block"));
}
void validate_key(string const & k) const
{
E(!k.empty()
&& k.find_first_not_of(constants::legal_key_name_bytes) == string::npos,
made_from,
F("malformed packet: invalid key name"));
}
void validate_public_key_data(string const & name, string const & keydata) const
{
string decoded = decode_base64_as<string>(keydata, origin::user);
Botan::SecureVector<Botan::byte> key_block
(reinterpret_cast<Botan::byte const *>(decoded.c_str()), decoded.size());
try
{
Botan::X509::load_key(key_block);
}
catch (Botan::Decoding_Error const & e)
{
E(false, origin::user,
F("malformed packet: invalid public key data for '%s': %s")
% name % e.what());
}
}
void validate_private_key_data(string const & name, string const & keydata) const
{
src/key_store.cc
OldNew
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
string sig_string;
ssh_agent & agent = s->get_agent();
//sign with ssh-agent (if connected)
E(agent.connected() || s->ssh_sign_mode != "only", origin::user,
F("you have chosen to sign only with ssh-agent but ssh-agent"
" does not seem to be running"));
if (s->ssh_sign_mode == "yes"
|| s->ssh_sign_mode == "check"
|| s->ssh_sign_mode == "only")
{
if (agent.connected()) {
//grab the monotone public key as an RSA_PublicKey
SecureVector<Botan::byte> pub_block;
pub_block.set(reinterpret_cast<Botan::byte const *>(key.pub().data()),
key.pub().size());
L(FL("make_signature: building %d-byte pub key") % pub_block.size());
shared_ptr<X509_PublicKey> x509_key =
shared_ptr<X509_PublicKey>(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key = shared_dynamic_cast<RSA_PublicKey>(x509_key);
if (!pub_key)
throw recoverable_failure(origin::system,
"Failed to get monotone RSA public key");
agent.sign_data(*pub_key, tosign, sig_string);
}
if (sig_string.length() <= 0)
L(FL("make_signature: monotone and ssh-agent keys do not match, will"
// See whether a lua hook will tell us the passphrase.
key_identity_info identity;
identity.given_name = id;
string lua_phrase;
if (lua.hook_get_passphrase(identity, lua_phrase))
phrase = utf8(lua_phrase, origin::user);
else
get_passphrase(phrase, id, key_id(), false, false);
int cycles = 1;
for (;;)
try
{
arc4_key.set(reinterpret_cast<Botan::byte const *>(phrase().data()),
phrase().size());
Pipe arc4_decryptor(get_cipher("ARC4", arc4_key, Botan::DECRYPTION));
arc4_decryptor.process_msg(old_priv());
// This is necessary because PKCS8::load_key() cannot currently
// recognize an unencrypted, raw-BER blob as such, but gets it
// right if it's PEM-coded.
SecureVector<Botan::byte> arc4_decrypt(arc4_decryptor.read_all());
Botan::DataSource_Memory ds(Botan::PEM_Code::encode(arc4_decrypt,
"PRIVATE KEY"));
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
pkcs8_key.reset(Botan::PKCS8::load_key(ds, lazy_rng::get()));
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
string sig_string;
ssh_agent & agent = s->get_agent();
//sign with ssh-agent (if connected)
E(agent.connected() || s->ssh_sign_mode != "only", origin::user,
F("you have chosen to sign only with ssh-agent but ssh-agent"
" does not seem to be running"));
if (s->ssh_sign_mode == "yes"
|| s->ssh_sign_mode == "check"
|| s->ssh_sign_mode == "only")
{
if (agent.connected()) {
//grab the monotone public key as an RSA_PublicKey
SecureVector<Botan::byte> pub_block
(reinterpret_cast<Botan::byte const *>(key.pub().data()),
key.pub().size());
L(FL("make_signature: building %d-byte pub key") % pub_block.size());
shared_ptr<X509_PublicKey> x509_key =
shared_ptr<X509_PublicKey>(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key = shared_dynamic_cast<RSA_PublicKey>(x509_key);
if (!pub_key)
throw recoverable_failure(origin::system,
"Failed to get monotone RSA public key");
agent.sign_data(*pub_key, tosign, sig_string);
}
if (sig_string.length() <= 0)
L(FL("make_signature: monotone and ssh-agent keys do not match, will"
// See whether a lua hook will tell us the passphrase.
key_identity_info identity;
identity.given_name = id;
string lua_phrase;
if (lua.hook_get_passphrase(identity, lua_phrase))
phrase = utf8(lua_phrase, origin::user);
else
get_passphrase(phrase, id, key_id(), false, false);
int cycles = 1;
for (;;)
try
{
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
arc4_key.resize(phrase().size());
arc4_key.copy(reinterpret_cast<Botan::byte const *>(phrase().data()),
phrase().size());
#else
arc4_key.set(reinterpret_cast<Botan::byte const *>(phrase().data()),
phrase().size());
#endif
Pipe arc4_decryptor(get_cipher("ARC4", arc4_key, Botan::DECRYPTION));
arc4_decryptor.process_msg(old_priv());
// This is necessary because PKCS8::load_key() cannot currently
// recognize an unencrypted, raw-BER blob as such, but gets it
// right if it's PEM-coded.
SecureVector<Botan::byte> arc4_decrypt(arc4_decryptor.read_all());
Botan::DataSource_Memory ds(Botan::PEM_Code::encode(arc4_decrypt,
"PRIVATE KEY"));
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
pkcs8_key.reset(Botan::PKCS8::load_key(ds, lazy_rng::get()));
src/sha1.cc
OldNew
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,23)
Botan::AutoSeeded_RNG rng;
Botan::Algorithm_Factory& af =
Botan::global_state().algorithm_factory();
const int milliseconds = 5000;
// timer argument was removed in 1.9.4
#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,4)
Botan::Default_Benchmark_Timer timer;
std::map<std::string, double> results =
Botan::algorithm_benchmark("SHA-1", milliseconds, timer, rng, af);
#else
std::map<std::string, double> results =
Botan::algorithm_benchmark("SHA-1", milliseconds, rng, af);
#endif
for(std::map<std::string, double>::const_iterator i = results.begin();
i != results.end(); ++i)
{
P(F("SHA-1 provider '%s': %s MiB/s") % i->first % i->second);
}
#else
int mebibytes = 100;
string test_str(mebibytes << 20, 'a');
data test_data(test_str, origin::internal);
id foo;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,23)
Botan::AutoSeeded_RNG rng;
Botan::Algorithm_Factory& af =
Botan::global_state().algorithm_factory();
const int milliseconds = 5000;
// timer argument was removed in 1.9.4
#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,4)
Botan::Default_Benchmark_Timer timer;
std::map<std::string, double> results =
Botan::algorithm_benchmark("SHA-1", milliseconds, timer, rng, af);
#elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,11)
std::map<std::string, double> results =
Botan::algorithm_benchmark("SHA-1", milliseconds, rng, af);
#else
std::map<std::string, double> results =
Botan::algorithm_benchmark("SHA-1", af, rng, milliseconds, 16);
#endif
for(std::map<std::string, double>::const_iterator i = results.begin();
i != results.end(); ++i)
{
P(F("SHA-1 provider '%s': %s MiB/s") % i->first % i->second);
}
#else
int mebibytes = 100;
string test_str(mebibytes << 20, 'a');
data test_data(test_str, origin::internal);
id foo;
src/ssh_agent.cc
OldNew
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
E(packet.length() == packet_loc, origin::system,
F("ssh_agent: get_keys: not all or too many packet bytes consumed,"
" location (%u), length (%i)")
% packet_loc
% packet.length());
return s->keys;
}
bool
ssh_agent::has_key(const keypair & key)
{
//grab the monotone public key as an RSA_PublicKey
SecureVector<Botan::byte> pub_block;
pub_block.set(reinterpret_cast<Botan::byte const *>((key.pub)().data()),
(key.pub)().size());
L(FL("has_key: building %d-byte pub key") % pub_block.size());
shared_ptr<X509_PublicKey> x509_key =
shared_ptr<X509_PublicKey>(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key = shared_dynamic_cast<RSA_PublicKey>(x509_key);
if (!pub_key)
throw recoverable_failure(origin::system,
"has_key: Failed to get monotone RSA public key");
vector<RSA_PublicKey> ssh_keys = get_keys();
for (vector<RSA_PublicKey>::const_iterator
si = ssh_keys.begin(); si != ssh_keys.end(); ++si)
{
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
E(packet.length() == packet_loc, origin::system,
F("ssh_agent: get_keys: not all or too many packet bytes consumed,"
" location (%u), length (%i)")
% packet_loc
% packet.length());
return s->keys;
}
bool
ssh_agent::has_key(const keypair & key)
{
//grab the monotone public key as an RSA_PublicKey
SecureVector<Botan::byte> pub_block
(reinterpret_cast<Botan::byte const *>((key.pub)().data()),
(key.pub)().size());
L(FL("has_key: building %d-byte pub key") % pub_block.size());
shared_ptr<X509_PublicKey> x509_key =
shared_ptr<X509_PublicKey>(Botan::X509::load_key(pub_block));
shared_ptr<RSA_PublicKey> pub_key = shared_dynamic_cast<RSA_PublicKey>(x509_key);
if (!pub_key)
throw recoverable_failure(origin::system,
"has_key: Failed to get monotone RSA public key");
vector<RSA_PublicKey> ssh_keys = get_keys();
for (vector<RSA_PublicKey>::const_iterator
si = ssh_keys.begin(); si != ssh_keys.end(); ++si)
{
src/gzip.cc
OldNew
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
* Start Compressing with Gzip *
*************************************************/
void Gzip_Compression::start_msg()
{
clear();
put_header();
pipe.start_msg();
count = 0;
}
/*************************************************
* Compress Input with Gzip *
*************************************************/
void Gzip_Compression::write(const byte input[], u32bit length)
{
count += length;
pipe.write(input, length);
zlib->stream.next_in = (Bytef*)input;
zlib->stream.avail_in = length;
while(zlib->stream.avail_in != 0)
{
zlib->stream.next_out = (Bytef*)buffer.begin();
zlib->stream.avail_out = buffer.size();
int rc = deflate(&(zlib->stream), Z_NO_FLUSH);
{
if (!no_writes)
throw Exception("Gzip_Decompression: start_msg after already writing");
pipe.start_msg();
datacount = 0;
pos = 0;
in_footer = false;
}
/*************************************************
* Decompress Input with Gzip *
*************************************************/
void Gzip_Decompression::write(const byte input[], u32bit length)
{
if(length) no_writes = false;
// If we're in the footer, take what we need, then go to the next block
if (in_footer)
{
u32bit eat_len = eat_footer(input, length);
input += eat_len;
length -= eat_len;
if (length == 0)
return;
}
// Check the gzip header
if (pos < sizeof(GZIP::GZIP_HEADER))
{
u32bit len = std::min((u32bit)sizeof(GZIP::GZIP_HEADER)-pos, length);
u32bit cmplen = len;
// The last byte is the OS flag - we don't care about that
if (pos + len - 1 >= GZIP::HEADER_POS_OS)
cmplen--;
if (std::memcmp(input, &GZIP::GZIP_HEADER[pos], cmplen) != 0)
{
throw Decoding_Error("Gzip_Decompression: Data integrity error in header");
}
input += len;
length -= len;
pos += len;
}
zlib->stream.avail_in = length;
}
}
}
/*************************************************
* Store the footer bytes *
*************************************************/
u32bit Gzip_Decompression::eat_footer(const byte input[], u32bit length)
{
if (footer.size() >= GZIP::FOOTER_LENGTH)
throw Decoding_Error("Gzip_Decompression: Data integrity error in footer");
u32bit eat_len = std::min(GZIP::FOOTER_LENGTH-footer.size(), length);
footer.append(input, eat_len);
if (footer.size() == GZIP::FOOTER_LENGTH)
{
check_footer();
clear();
}
return eat_len;
}
/*************************************************
* Check the gzip footer *
*************************************************/
throw Exception("Gzip_Decompression: Error finalizing decompression");
pipe.end_msg();
// 4 byte CRC32, and 4 byte length field
SecureVector<byte> buf(4);
SecureVector<byte> tmpbuf(4);
pipe.read(tmpbuf.begin(), tmpbuf.size(), Pipe::LAST_MESSAGE);
// CRC32 is the reverse order to what gzip expects.
for (int i = 0; i < 4; i++)
buf[3-i] = tmpbuf[i];
tmpbuf.set(footer.begin(), 4);
if (buf != tmpbuf)
throw Decoding_Error("Gzip_Decompression: Data integrity error - CRC32 error");
// Check the length matches - it is encoded LSB-first
for (int i = 0; i < 4; i++)
{
if (footer.begin()[GZIP::FOOTER_LENGTH-1-i] != get_byte(i, datacount))
throw Decoding_Error("Gzip_Decompression: Data integrity error - incorrect length");
}
}
/*************************************************
throw Exception("Gzip_Decompression: didn't find footer");
}
/*************************************************
* Clean up Decompression Context *
*************************************************/
void Gzip_Decompression::clear()
{
no_writes = true;
inflateReset(&(zlib->stream));
footer.destroy();
pos = 0;
datacount = 0;
}
}
// Local Variables:
// mode: C++
// fill-column: 76
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
* Start Compressing with Gzip *
*************************************************/
void Gzip_Compression::start_msg()
{
clear();
put_header();
pipe.start_msg();
count = 0;
}
/*************************************************
* Compress Input with Gzip *
*************************************************/
void Gzip_Compression::write(const byte input[], filter_length_t length)
{
count += length;
pipe.write(input, length);
zlib->stream.next_in = (Bytef*)input;
zlib->stream.avail_in = length;
while(zlib->stream.avail_in != 0)
{
zlib->stream.next_out = (Bytef*)buffer.begin();
zlib->stream.avail_out = buffer.size();
int rc = deflate(&(zlib->stream), Z_NO_FLUSH);
{
if (!no_writes)
throw Exception("Gzip_Decompression: start_msg after already writing");
pipe.start_msg();
datacount = 0;
pos = 0;
in_footer = false;
}
/*************************************************
* Decompress Input with Gzip *
*************************************************/
void Gzip_Decompression::write(const byte input[], filter_length_t length)
{
if(length) no_writes = false;
// If we're in the footer, take what we need, then go to the next block
if (in_footer)
{
u32bit eat_len = eat_footer(input, length);
input += eat_len;
length -= eat_len;
if (length == 0)
return;
}
// Check the gzip header
if (pos < sizeof(GZIP::GZIP_HEADER))
{
filter_length_t len = std::min((filter_length_t)sizeof(GZIP::GZIP_HEADER)-pos, length);
filter_length_t cmplen = len;
// The last byte is the OS flag - we don't care about that
if (pos + len - 1 >= GZIP::HEADER_POS_OS)
cmplen--;
if (std::memcmp(input, &GZIP::GZIP_HEADER[pos], cmplen) != 0)
{
throw Decoding_Error("Gzip_Decompression: Data integrity error in header");
}
input += len;
length -= len;
pos += len;
}
zlib->stream.avail_in = length;
}
}
}
/*************************************************
* Store the footer bytes *
*************************************************/
u32bit Gzip_Decompression::eat_footer(const byte input[], u32bit length)
{
if (footer.size() >= GZIP::FOOTER_LENGTH)
throw Decoding_Error("Gzip_Decompression: Data integrity error in footer");
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
size_t eat_len = std::min(GZIP::FOOTER_LENGTH-footer.size(),
static_cast<size_t>(length));
footer += std::make_pair(input, eat_len);
#else
u32bit eat_len = std::min(GZIP::FOOTER_LENGTH-footer.size(), length);
footer.append(input, eat_len);
#endif
if (footer.size() == GZIP::FOOTER_LENGTH)
{
check_footer();
clear();
}
return eat_len;
}
/*************************************************
* Check the gzip footer *
*************************************************/
throw Exception("Gzip_Decompression: Error finalizing decompression");
pipe.end_msg();
// 4 byte CRC32, and 4 byte length field
SecureVector<byte> buf(4);
SecureVector<byte> tmpbuf(4);
pipe.read(tmpbuf.begin(), tmpbuf.size(), Pipe::LAST_MESSAGE);
// CRC32 is the reverse order to what gzip expects.
for (int i = 0; i < 4; i++)
buf[3-i] = tmpbuf[i];
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
tmpbuf.resize(4);
tmpbuf.copy(footer.begin(), 4);
#else
tmpbuf.set(footer.begin(), 4);
#endif
if (buf != tmpbuf)
throw Decoding_Error("Gzip_Decompression: Data integrity error - CRC32 error");
// Check the length matches - it is encoded LSB-first
for (int i = 0; i < 4; i++)
{
if (footer.begin()[GZIP::FOOTER_LENGTH-1-i] != get_byte(i, datacount))
throw Decoding_Error("Gzip_Decompression: Data integrity error - incorrect length");
}
}
/*************************************************
throw Exception("Gzip_Decompression: didn't find footer");
}
/*************************************************
* Clean up Decompression Context *
*************************************************/
void Gzip_Decompression::clear()
{
no_writes = true;
inflateReset(&(zlib->stream));
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
footer.clear();
#else
footer.destroy();
#endif
pos = 0;
datacount = 0;
}
}
// Local Variables:
// mode: C++
// fill-column: 76
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
src/gzip.hh
OldNew
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*************************************************
* Gzip Compressor Header File *
* (C) 2001 Peter J Jones (pjones@pmade.org) *
* 2001-2004 Jack Lloyd *
*************************************************/
#ifndef BOTAN_EXT_GZIP_H__
#define BOTAN_EXT_GZIP_H__
#include <botan/filter.h>
#include <botan/pipe.h>
namespace Botan {
namespace GZIP {
/* A basic header - we only need to set the IDs and compression method */
const byte GZIP_HEADER[] = {
0x1f, 0x8b, /* Magic ID bytes */
0x08, /* Compression method of 'deflate' */
0x00, /* Flags all empty */
0x00, 0x00, 0x00, 0x00, /* MTIME */
0x00, /* Extra flags */
0xff, /* Operating system (unknown) */
};
const unsigned int HEADER_POS_OS = 9;
const unsigned int FOOTER_LENGTH = 8;
}
/*************************************************
* Gzip Compression Filter *
*************************************************/
class Gzip_Compression : public Filter
{
public:
void write(const byte input[], u32bit length);
void start_msg();
void end_msg();
std::string name() const { return "Gzip_Compression"; }
Gzip_Compression(u32bit = 1);
~Gzip_Compression();
private:
void clear();
void put_header();
void put_footer();
const u32bit level;
SecureVector<byte> buffer;
class Zlib_Stream* zlib;
Pipe pipe; /* A pipe for the crc32 processing */
u32bit count;
};
/*************************************************
* Gzip Decompression Filter *
*************************************************/
class Gzip_Decompression : public Filter
{
public:
void write(const byte input[], u32bit length);
void start_msg();
void end_msg();
std::string name() const { return "Gzip_Decompression"; }
Gzip_Decompression();
~Gzip_Decompression();
private:
u32bit eat_footer(const byte input[], u32bit length);
void check_footer();
void clear();
SecureVector<byte> buffer;
class Zlib_Stream* zlib;
bool no_writes;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*************************************************
* Gzip Compressor Header File *
* (C) 2001 Peter J Jones (pjones@pmade.org) *
* 2001-2004 Jack Lloyd *
*************************************************/
#ifndef BOTAN_EXT_GZIP_H__
#define BOTAN_EXT_GZIP_H__
#include <botan/version.h>
#include <botan/filter.h>
#include <botan/pipe.h>
namespace Botan {
namespace GZIP {
/* A basic header - we only need to set the IDs and compression method */
const byte GZIP_HEADER[] = {
0x1f, 0x8b, /* Magic ID bytes */
0x08, /* Compression method of 'deflate' */
0x00, /* Flags all empty */
0x00, 0x00, 0x00, 0x00, /* MTIME */
0x00, /* Extra flags */
0xff, /* Operating system (unknown) */
};
const unsigned int HEADER_POS_OS = 9;
const unsigned int FOOTER_LENGTH = 8;
}
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
typedef size_t filter_length_t;
#else
typedef u32bit filter_length_t;
#endif
/*************************************************
* Gzip Compression Filter *
*************************************************/
class Gzip_Compression : public Filter
{
public:
void write(const byte input[], filter_length_t length);
void start_msg();
void end_msg();
std::string name() const { return "Gzip_Compression"; }
Gzip_Compression(u32bit = 1);
~Gzip_Compression();
private:
void clear();
void put_header();
void put_footer();
const u32bit level;
SecureVector<byte> buffer;
class Zlib_Stream* zlib;
Pipe pipe; /* A pipe for the crc32 processing */
u32bit count;
};
/*************************************************
* Gzip Decompression Filter *
*************************************************/
class Gzip_Decompression : public Filter
{
public:
void write(const byte input[], filter_length_t length);
void start_msg();
void end_msg();
std::string name() const { return "Gzip_Decompression"; }
Gzip_Decompression();
~Gzip_Decompression();
private:
u32bit eat_footer(const byte input[], u32bit length);
void check_footer();
void clear();
SecureVector<byte> buffer;
class Zlib_Stream* zlib;
bool no_writes;
src/key_packet.cc
OldNew
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
made_from,
F("malformed key_packet: invalid base64 block"));
}
void validate_key(string const & k) const
{
E(!k.empty()
&& k.find_first_not_of(constants::legal_key_name_bytes) == string::npos,
made_from,
F("malformed key_packet: invalid key name"));
}
void validate_public_key_data(string const & name, string const & keydata) const
{
string decoded = decode_base64_as<string>(keydata, origin::user);
Botan::SecureVector<Botan::byte> key_block;
key_block.set(reinterpret_cast<Botan::byte const *>(decoded.c_str()), decoded.size());
try
{
Botan::X509::load_key(key_block);
}
catch (Botan::Decoding_Error const & e)
{
E(false, origin::user,
F("malformed key_packet: invalid public key data for '%s': %s")
% name % e.what());
}
}
void validate_private_key_data(string const & name, string const & keydata) const
{
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
made_from,
F("malformed key_packet: invalid base64 block"));
}
void validate_key(string const & k) const
{
E(!k.empty()
&& k.find_first_not_of(constants::legal_key_name_bytes) == string::npos,
made_from,
F("malformed key_packet: invalid key name"));
}
void validate_public_key_data(string const & name, string const & keydata) const
{
string decoded = decode_base64_as<string>(keydata, origin::user);
Botan::SecureVector<Botan::byte> key_block
(reinterpret_cast<Botan::byte const *>(decoded.c_str()), decoded.size());
try
{
Botan::X509::load_key(key_block);
}
catch (Botan::Decoding_Error const & e)
{
E(false, origin::user,
F("malformed key_packet: invalid public key data for '%s': %s")
% name % e.what());
}
}
void validate_private_key_data(string const & name, string const & keydata) const
{

General Comments

Comment 1 by Martin von Gagern, Sep 7, 2011

Updated patch attached to issue 182, which adjusts the runtime check 
as well. Is there some way to update this code review here? Or to 
close it and start a new one?

Comment 2 by Markus Wanner, Sep 23, 2013

This has been committed, thanks. Issue 182 is closed as well.
Status: Accepted

Comment 3 by Markus Wanner, Oct 24, 2013

The status have been updated.
Status: Fixed
Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status