1 /**
2 * @file cryptopp.cpp
3 * @brief Crypto layer using Crypto++
4 *
5 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
6 *
7 * This file is part of the MEGA SDK - Client Access Engine.
8 *
9 * Applications using the MEGA API must present a valid application key
10 * and comply with the the rules set forth in the Terms of Service.
11 *
12 * The MEGA SDK is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * @copyright Simplified (2-clause) BSD License.
17 *
18 * You should have received a copy of the license along with this
19 * program.
20 */
21
22 #include "mega.h"
23
24 namespace mega {
25 #ifndef htobe64
26 #define htobe64(x) (((uint64_t)htonl((uint32_t)((x) >> 32))) | (((uint64_t)htonl((uint32_t)x)) << 32))
27 #endif
28
29 using namespace CryptoPP;
30
31 // cryptographically strong random byte sequence
genblock(byte * buf,size_t len)32 void PrnGen::genblock(byte* buf, size_t len)
33 {
34 GenerateBlock(buf, len);
35 }
36
37 // random number from 0 ... max-1
genuint32(uint64_t max)38 uint32_t PrnGen::genuint32(uint64_t max)
39 {
40 uint32_t t;
41
42 genblock((byte*)&t, sizeof t);
43
44 return (uint32_t)(((uint64_t)t) / ((((uint64_t)(~(uint32_t)0)) + 1) / max));
45 }
46
SymmCipher(const byte * key)47 SymmCipher::SymmCipher(const byte* key)
48 {
49 setkey(key);
50 }
51
52 byte SymmCipher::zeroiv[BLOCKSIZE];
53
setkey(const byte * newkey,int type)54 void SymmCipher::setkey(const byte* newkey, int type)
55 {
56 memcpy(key, newkey, KEYLENGTH);
57
58 if (!type)
59 {
60 xorblock(newkey + KEYLENGTH, key);
61 }
62
63 aesecb_e.SetKey(key, KEYLENGTH);
64 aesecb_d.SetKey(key, KEYLENGTH);
65
66 aescbc_e.SetKeyWithIV(key, KEYLENGTH, zeroiv);
67 aescbc_d.SetKeyWithIV(key, KEYLENGTH, zeroiv);
68
69 aesccm8_e.SetKeyWithIV(key, KEYLENGTH, zeroiv);
70 aesccm8_d.SetKeyWithIV(key, KEYLENGTH, zeroiv);
71
72 aesccm16_e.SetKeyWithIV(key, KEYLENGTH, zeroiv);
73 aesccm16_d.SetKeyWithIV(key, KEYLENGTH, zeroiv);
74
75 aesgcm_e.SetKeyWithIV(key, KEYLENGTH, zeroiv);
76 aesgcm_d.SetKeyWithIV(key, KEYLENGTH, zeroiv);
77 }
78
setkey(const string * key)79 bool SymmCipher::setkey(const string* key)
80 {
81 if (key->size() == FILENODEKEYLENGTH || key->size() == FOLDERNODEKEYLENGTH)
82 {
83 setkey((const byte*)key->data(), (key->size() == FOLDERNODEKEYLENGTH) ? FOLDERNODE : FILENODE);
84
85 return true;
86 }
87
88 return false;
89 }
90
cbc_encrypt(byte * data,size_t len,const byte * iv)91 void SymmCipher::cbc_encrypt(byte* data, size_t len, const byte* iv)
92 {
93 aescbc_e.Resynchronize(iv ? iv : zeroiv);
94 aescbc_e.ProcessData(data, data, len);
95 }
96
cbc_decrypt(byte * data,size_t len,const byte * iv)97 void SymmCipher::cbc_decrypt(byte* data, size_t len, const byte* iv)
98 {
99 aescbc_d.Resynchronize(iv ? iv : zeroiv);
100 aescbc_d.ProcessData(data, data, len);
101 }
102
cbc_encrypt_pkcs_padding(const string * data,const byte * iv,string * result)103 void SymmCipher::cbc_encrypt_pkcs_padding(const string *data, const byte *iv, string *result)
104 {
105 aescbc_e.Resynchronize(iv ? iv : zeroiv);
106 StringSource(*data, true,
107 new StreamTransformationFilter( aescbc_e, new StringSink( *result ),
108 StreamTransformationFilter::PKCS_PADDING));
109 }
110
cbc_decrypt_pkcs_padding(const std::string * data,const byte * iv,string * result)111 void SymmCipher::cbc_decrypt_pkcs_padding(const std::string *data, const byte *iv, string *result)
112 {
113 aescbc_d.Resynchronize(iv ? iv : zeroiv);
114 StringSource(*data, true,
115 new StreamTransformationFilter( aescbc_d, new StringSink( *result ),
116 StreamTransformationFilter::PKCS_PADDING));
117 }
118
ecb_encrypt(byte * data,byte * dst,size_t len)119 void SymmCipher::ecb_encrypt(byte* data, byte* dst, size_t len)
120 {
121 aesecb_e.ProcessData(dst ? dst : data, data, len);
122 }
123
ecb_decrypt(byte * data,size_t len)124 void SymmCipher::ecb_decrypt(byte* data, size_t len)
125 {
126 aesecb_d.ProcessData(data, data, len);
127 }
128
ccm_encrypt(const string * data,const byte * iv,unsigned ivlen,unsigned taglen,string * result)129 void SymmCipher::ccm_encrypt(const string *data, const byte *iv, unsigned ivlen, unsigned taglen, string *result)
130 {
131 if (taglen == 16)
132 {
133 aesccm16_e.Resynchronize(iv, ivlen);
134 aesccm16_e.SpecifyDataLengths(0, data->size(), 0);
135 StringSource(*data, true, new AuthenticatedEncryptionFilter(aesccm16_e, new StringSink(*result)));
136 }
137 else if (taglen == 8)
138 {
139 aesccm8_e.Resynchronize(iv, ivlen);
140 aesccm8_e.SpecifyDataLengths(0, data->size(), 0);
141 StringSource(*data, true, new AuthenticatedEncryptionFilter(aesccm8_e, new StringSink(*result)));
142 }
143 }
144
ccm_decrypt(const string * data,const byte * iv,unsigned ivlen,unsigned taglen,string * result)145 bool SymmCipher::ccm_decrypt(const string *data, const byte *iv, unsigned ivlen, unsigned taglen, string *result)
146 {
147 try {
148 if (taglen == 16)
149 {
150 aesccm16_d.Resynchronize(iv, ivlen);
151 aesccm16_d.SpecifyDataLengths(0, data->size() - taglen, 0);
152 StringSource(*data, true, new AuthenticatedDecryptionFilter(aesccm16_d, new StringSink(*result)));
153 }
154 else if (taglen == 8)
155 {
156 aesccm8_d.Resynchronize(iv, ivlen);
157 aesccm8_d.SpecifyDataLengths(0, data->size() - taglen, 0);
158 StringSource(*data, true, new AuthenticatedDecryptionFilter(aesccm8_d, new StringSink(*result)));
159 }
160 } catch (HashVerificationFilter::HashVerificationFailed e)
161 {
162 result->clear();
163 LOG_err << "Failed AES-CCM decryption: " << e.GetWhat();
164 return false;
165 }
166 return true;
167 }
168
gcm_encrypt(const string * data,const byte * iv,unsigned ivlen,unsigned taglen,string * result)169 void SymmCipher::gcm_encrypt(const string *data, const byte *iv, unsigned ivlen, unsigned taglen, string *result)
170 {
171 aesgcm_e.Resynchronize(iv, ivlen);
172 StringSource(*data, true, new AuthenticatedEncryptionFilter(aesgcm_e, new StringSink(*result), false, taglen));
173 }
174
gcm_decrypt(const string * data,const byte * iv,unsigned ivlen,unsigned taglen,string * result)175 bool SymmCipher::gcm_decrypt(const string *data, const byte *iv, unsigned ivlen, unsigned taglen, string *result)
176 {
177 aesgcm_d.Resynchronize(iv, ivlen);
178 try {
179 StringSource(*data, true, new AuthenticatedDecryptionFilter(aesgcm_d, new StringSink(*result), taglen));
180 } catch (HashVerificationFilter::HashVerificationFailed e)
181 {
182 result->clear();
183 LOG_err << "Failed AES-GCM decryption: " << e.GetWhat();
184 return false;
185 }
186 return true;
187 }
188
serializekeyforjs(string * d)189 void SymmCipher::serializekeyforjs(string *d)
190 {
191 char invertedkey[BLOCKSIZE];
192 std::stringstream ss;
193
194 ss << "[";
195 for (int i=0; i<BLOCKSIZE; i++)
196 {
197 invertedkey[i] = key[BLOCKSIZE - i - 1];
198 }
199
200 int32_t *k = (int32_t *)invertedkey;
201 for (int i = 3; i >= 0; i--)
202 {
203 ss << k[i];
204 if (i)
205 {
206 ss << ",";
207 }
208 }
209 ss << "]";
210 *d = ss.str();
211 }
212
setint64(int64_t value,byte * data)213 void SymmCipher::setint64(int64_t value, byte* data)
214 {
215 #if __BYTE_ORDER == __LITTLE_ENDIAN
216 value = htobe64(value);
217 #else
218 #if __BYTE_ORDER != __BIG_ENDIAN
219 #error "Unknown or unsupported endianness"
220 #endif
221 #endif
222 memcpy(data, (char*)&value, sizeof value);
223 }
224
xorblock(const byte * src,byte * dst)225 void SymmCipher::xorblock(const byte* src, byte* dst)
226 {
227 long* lsrc = (long*)src;
228 long* ldst = (long*)dst;
229
230 for (int i = BLOCKSIZE / sizeof(long); i--;)
231 {
232 ldst[i] ^= lsrc[i];
233 }
234 }
235
xorblock(const byte * src,byte * dst,int len)236 void SymmCipher::xorblock(const byte* src, byte* dst, int len)
237 {
238 while (len--)
239 {
240 dst[len] ^= src[len];
241 }
242 }
243
incblock(byte * dst,unsigned len)244 void SymmCipher::incblock(byte* dst, unsigned len)
245 {
246 while (len)
247 {
248 if (++dst[--len])
249 {
250 break;
251 }
252 }
253 }
254
SymmCipher(const SymmCipher & ref)255 SymmCipher::SymmCipher(const SymmCipher &ref)
256 {
257 setkey(ref.key);
258 }
259
operator =(const SymmCipher & ref)260 SymmCipher& SymmCipher::operator=(const SymmCipher& ref)
261 {
262 setkey(ref.key);
263 return *this;
264 }
265
266 // encryption: data must be NUL-padded to BLOCKSIZE
267 // decryption: data must be padded to BLOCKSIZE
268 // len must be < 2^31
ctr_crypt(byte * data,unsigned len,m_off_t pos,ctr_iv ctriv,byte * mac,bool encrypt,bool initmac)269 void SymmCipher::ctr_crypt(byte* data, unsigned len, m_off_t pos, ctr_iv ctriv, byte* mac, bool encrypt, bool initmac)
270 {
271 assert(!(pos & (KEYLENGTH - 1)));
272
273 byte ctr[BLOCKSIZE], tmp[BLOCKSIZE];
274
275 MemAccess::set<int64_t>(ctr,ctriv);
276 setint64(pos / BLOCKSIZE, ctr + sizeof ctriv);
277
278 if (mac && initmac)
279 {
280 memcpy(mac, ctr, sizeof ctriv);
281 memcpy(mac + sizeof ctriv, ctr, sizeof ctriv);
282 }
283
284 while ((int)len > 0)
285 {
286 if (encrypt)
287 {
288 if(mac)
289 {
290 xorblock(data, mac);
291 ecb_encrypt(mac);
292 }
293
294 ecb_encrypt(ctr, tmp);
295 xorblock(tmp, data);
296 }
297 else
298 {
299 ecb_encrypt(ctr, tmp);
300 xorblock(tmp, data);
301
302 if (mac)
303 {
304 if (len >= (unsigned)BLOCKSIZE)
305 {
306 xorblock(data, mac);
307 }
308 else
309 {
310 xorblock(data, mac, len);
311 }
312
313 ecb_encrypt(mac);
314 }
315 }
316
317 len -= BLOCKSIZE;
318 data += BLOCKSIZE;
319
320 incblock(ctr);
321 }
322 }
323
rsaencrypt(Integer * key,Integer * m)324 static void rsaencrypt(Integer* key, Integer* m)
325 {
326 *m = a_exp_b_mod_c(*m, key[AsymmCipher::PUB_E], key[AsymmCipher::PUB_PQ]);
327 }
328
rawencrypt(const byte * plain,size_t plainlen,byte * buf,size_t buflen)329 unsigned AsymmCipher::rawencrypt(const byte* plain, size_t plainlen, byte* buf, size_t buflen)
330 {
331 Integer t(plain, plainlen);
332
333 rsaencrypt(key, &t);
334
335 unsigned i = t.ByteCount();
336
337 if (i > buflen)
338 {
339 return 0;
340 }
341
342 while (i--)
343 {
344 *buf++ = t.GetByte(i);
345 }
346
347 return t.ByteCount();
348 }
349
encrypt(PrnGen & rng,const byte * plain,size_t plainlen,byte * buf,size_t buflen)350 int AsymmCipher::encrypt(PrnGen &rng, const byte* plain, size_t plainlen, byte* buf, size_t buflen)
351 {
352 if (key[PUB_PQ].ByteCount() + 2 > buflen)
353 {
354 return 0;
355 }
356
357 if (buf != plain)
358 {
359 memcpy(buf, plain, plainlen);
360 }
361
362 // add random padding
363 rng.genblock(buf + plainlen, key[PUB_PQ].ByteCount() - plainlen - 2);
364
365 Integer t(buf, key[PUB_PQ].ByteCount() - 2);
366
367 rsaencrypt(key, &t);
368
369 int i = t.BitCount();
370
371 byte* ptr = buf;
372
373 *ptr++ = (byte)(i >> 8);
374 *ptr++ = (byte)i;
375
376 i = t.ByteCount();
377
378 while (i--)
379 {
380 *ptr++ = t.GetByte(i);
381 }
382
383 return int(ptr - buf);
384 }
385
rsadecrypt(Integer * key,Integer * m)386 static void rsadecrypt(Integer* key, Integer* m)
387 {
388 Integer xp = a_exp_b_mod_c(*m % key[AsymmCipher::PRIV_P],
389 key[AsymmCipher::PRIV_D] % (key[AsymmCipher::PRIV_P] - Integer::One()),
390 key[AsymmCipher::PRIV_P]);
391 Integer xq = a_exp_b_mod_c(*m % key[AsymmCipher::PRIV_Q],
392 key[AsymmCipher::PRIV_D] % (key[AsymmCipher::PRIV_Q] - Integer::One()),
393 key[AsymmCipher::PRIV_Q]);
394
395 if (xp > xq)
396 {
397 *m = key[AsymmCipher::PRIV_Q] - (((xp - xq) * key[AsymmCipher::PRIV_U]) % key[AsymmCipher::PRIV_Q]);
398 }
399 else
400 {
401 *m = ((xq - xp) * key[AsymmCipher::PRIV_U]) % key[AsymmCipher::PRIV_Q];
402 }
403
404 *m = *m * key[AsymmCipher::PRIV_P] + xp;
405 }
406
rawdecrypt(const byte * cipher,size_t cipherlen,byte * buf,size_t buflen)407 unsigned AsymmCipher::rawdecrypt(const byte* cipher, size_t cipherlen, byte* buf, size_t buflen)
408 {
409 Integer m(cipher, cipherlen);
410
411 rsadecrypt(key, &m);
412
413 unsigned i = m.ByteCount();
414
415 if (i > buflen)
416 {
417 return 0;
418 }
419
420 while (i--)
421 {
422 *buf++ = m.GetByte(i);
423 }
424
425 return m.ByteCount();
426 }
427
decrypt(const byte * cipher,size_t cipherlen,byte * out,size_t numbytes)428 int AsymmCipher::decrypt(const byte* cipher, size_t cipherlen, byte* out, size_t numbytes)
429 {
430 Integer m;
431
432 if (!decodeintarray(&m, 1, cipher, int(cipherlen)))
433 {
434 return 0;
435 }
436
437 rsadecrypt(key, &m);
438
439 size_t l = key[AsymmCipher::PRIV_P].ByteCount() + key[AsymmCipher::PRIV_Q].ByteCount() - 2;
440
441 if (m.ByteCount() > l)
442 {
443 l = m.ByteCount();
444 }
445
446 l -= numbytes;
447
448 while (numbytes--)
449 {
450 out[numbytes] = m.GetByte(l++);
451 }
452
453 return 1;
454 }
455
setkey(int numints,const byte * data,int len)456 int AsymmCipher::setkey(int numints, const byte* data, int len)
457 {
458 int ret = decodeintarray(key, numints, data, len);
459 padding = (numints == PUBKEY && ret) ? (len - key[PUB_PQ].ByteCount() - key[PUB_E].ByteCount() - 4) : 0;
460 return ret;
461 }
462
resetkey()463 void AsymmCipher::resetkey()
464 {
465 for (int i = 0; i < PRIVKEY; i++)
466 {
467 key[i] = Integer::Zero();
468 padding = 0;
469 }
470 }
471
serializekeyforjs(string & d)472 void AsymmCipher::serializekeyforjs(string& d)
473 {
474 unsigned sizePQ = key[PUB_PQ].ByteCount();
475 unsigned sizeE = key[PUB_E].ByteCount();
476 char c;
477
478 d.clear();
479 d.reserve(sizePQ + sizeE + padding);
480
481 for (int j = key[PUB_PQ].ByteCount(); j--;)
482 {
483 c = key[PUB_PQ].GetByte(j);
484 d.append(&c, sizeof c);
485 }
486
487 // accounts created by webclient use 4 bytes for serialization of exponent
488 // --> add left-padding up to 4 bytes for compatibility reasons
489 c = 0;
490 for (unsigned j = 0; j < padding; j++)
491 {
492 d.append(&c, sizeof c);
493 }
494
495 for (int j = sizeE; j--;)
496 {
497 c = key[PUB_E].GetByte(j); // returns 0 if out-of-range
498 d.append(&c, sizeof c);
499 }
500 }
501
serializekey(string * d,int keytype)502 void AsymmCipher::serializekey(string* d, int keytype)
503 {
504 serializeintarray(key, keytype, d);
505 }
506
serializeintarray(Integer * t,int numints,string * d,bool headers)507 void AsymmCipher::serializeintarray(Integer* t, int numints, string* d, bool headers)
508 {
509 unsigned size = 0;
510 char c;
511
512 for (int i = numints; i--;)
513 {
514 size += t[i].ByteCount();
515
516 if (headers)
517 {
518 size += 2;
519 }
520 }
521
522 d->reserve(d->size() + size);
523
524 for (int i = 0; i < numints; i++)
525 {
526 if (headers)
527 {
528 c = static_cast<char>(t[i].BitCount() >> 8);
529 d->append(&c, sizeof c);
530
531 c = (char)t[i].BitCount();
532 d->append(&c, sizeof c);
533 }
534
535 for (int j = t[i].ByteCount(); j--;)
536 {
537 c = t[i].GetByte(j);
538 d->append(&c, sizeof c);
539 }
540 }
541 }
542
decodeintarray(Integer * t,int numints,const byte * data,int len)543 int AsymmCipher::decodeintarray(Integer* t, int numints, const byte* data, int len)
544 {
545 int p, i, n;
546
547 p = 0;
548
549 for (i = 0; i < numints; i++)
550 {
551 if (p + 2 > len)
552 {
553 break;
554 }
555
556 n = ((data[p] << 8) + data[p + 1] + 7) >> 3;
557
558 p += 2;
559 if (p + n > len)
560 {
561 break;
562 }
563
564 t[i] = Integer(data + p, n);
565
566 p += n;
567 }
568
569 return i == numints && len - p < 16;
570 }
571
isvalid(int keytype)572 int AsymmCipher::isvalid(int keytype)
573 {
574 if (keytype == PUBKEY)
575 {
576 return key[PUB_PQ].BitCount() && key[PUB_E].BitCount();
577 }
578
579 if (keytype == PRIVKEY)
580 {
581 return key[PRIV_P].BitCount() &&
582 key[PRIV_Q].BitCount() &&
583 key[PRIV_D].BitCount() &&
584 key[PRIV_U].BitCount();
585 }
586
587 return 0;
588 }
589
590 // adapted from CryptoPP, rsa.cpp
591 class RSAPrimeSelector : public PrimeSelector
592 {
593 Integer m_e;
594
595 public:
RSAPrimeSelector(const Integer & e)596 RSAPrimeSelector(const Integer &e) : m_e(e) { }
597
IsAcceptable(const Integer & candidate) const598 bool IsAcceptable(const Integer &candidate) const
599 {
600 return RelativelyPrime(m_e, candidate - Integer::One());
601 }
602 };
603
604 // generate RSA keypair
genkeypair(PrnGen & rng,Integer * privk,Integer * pubk,int size)605 void AsymmCipher::genkeypair(PrnGen &rng, Integer* privk, Integer* pubk, int size)
606 {
607 pubk[PUB_E] = 17;
608
609 RSAPrimeSelector selector(pubk[PUB_E]);
610 AlgorithmParameters primeParam
611 = MakeParametersForTwoPrimesOfEqualSize(size)
612 (Name::PointerToPrimeSelector(), selector.GetSelectorPointer());
613
614 privk[PRIV_P].GenerateRandom(rng, primeParam);
615 privk[PRIV_Q].GenerateRandom(rng, primeParam);
616
617 privk[PRIV_D] = pubk[PUB_E].InverseMod(LCM(privk[PRIV_P] - Integer::One(), privk[PRIV_Q] - Integer::One()));
618 pubk[PUB_PQ] = privk[PRIV_P] * privk[PRIV_Q];
619 privk[PRIV_U] = privk[PRIV_P].InverseMod(privk[PRIV_Q]);
620 }
621
add(const byte * data,unsigned len)622 void Hash::add(const byte* data, unsigned len)
623 {
624 hash.Update(data, len);
625 }
626
get(string * out)627 void Hash::get(string* out)
628 {
629 out->resize(hash.DigestSize());
630 hash.Final((byte*)out->data());
631 }
632
add(const byte * data,unsigned int len)633 void HashSHA256::add(const byte *data, unsigned int len)
634 {
635 hash.Update(data, len);
636 }
637
get(std::string * retStr)638 void HashSHA256::get(std::string *retStr)
639 {
640 retStr->resize(hash.DigestSize());
641 hash.Final((byte*)retStr->data());
642 }
643
add(const byte * data,unsigned len)644 void HashCRC32::add(const byte* data, unsigned len)
645 {
646 hash.Update(data, len);
647 }
648
get(byte * out)649 void HashCRC32::get(byte* out)
650 {
651 hash.Final(out);
652 }
653
HMACSHA256(const byte * key,size_t length)654 HMACSHA256::HMACSHA256(const byte *key, size_t length)
655 : hmac(key, length)
656 {
657 }
658
add(const byte * data,size_t len)659 void HMACSHA256::add(const byte *data, size_t len)
660 {
661 hmac.Update(data, len);
662 }
663
get(byte * out)664 void HMACSHA256::get(byte *out)
665 {
666 hmac.Final(out);
667 }
668
PBKDF2_HMAC_SHA512()669 PBKDF2_HMAC_SHA512::PBKDF2_HMAC_SHA512()
670 {
671 }
672
deriveKey(byte * derivedkey,size_t derivedkeyLen,byte * pwd,size_t pwdLen,byte * salt,size_t saltLen,unsigned int iterations)673 void PBKDF2_HMAC_SHA512::deriveKey(byte* derivedkey, size_t derivedkeyLen,
674 byte* pwd, size_t pwdLen,
675 byte* salt, size_t saltLen, unsigned int iterations)
676 {
677 pbkdf2.DeriveKey(
678 // buffer that holds the derived key
679 derivedkey, derivedkeyLen,
680 // purpose byte. unused by this PBKDF implementation.
681 0x00,
682 // password bytes. careful to be consistent with encoding...
683 pwd, pwdLen,
684 // salt bytes
685 salt, saltLen,
686 // iteration count. See SP 800-132 for details. You want this as large as you can tolerate.
687 // make sure to use the same iteration count on both sides...
688 iterations
689 );
690 }
691
692 } // namespace
693