int main(void) { sodium_init(); //create random chain key unsigned char chain_key[crypto_auth_BYTES]; randombytes_buf(chain_key, crypto_auth_BYTES); //print first chain key printf("Chain key (%i Bytes):\n", crypto_auth_BYTES); print_hex(chain_key, crypto_auth_BYTES, 30); putchar('\n'); int status; //derive message key from chain key unsigned char message_key[crypto_auth_BYTES]; status = derive_message_key(message_key, chain_key); sodium_memzero(chain_key, crypto_auth_BYTES); if (status != 0) { fprintf(stderr, "ERROR: Failed to derive message key. (%i)\n", status); sodium_memzero(message_key, crypto_auth_BYTES); return status; } //print message key printf("Message key (%i Bytes):\n", crypto_auth_BYTES); print_hex(message_key, crypto_auth_BYTES, 30); putchar('\n'); sodium_memzero(message_key, crypto_auth_BYTES); return EXIT_SUCCESS; }
int crypto_auth_hmacsha512_init(crypto_auth_hmacsha512_state *state, const unsigned char *key, size_t keylen) { unsigned char pad[128]; unsigned char khash[64]; size_t i; if (keylen > 128) { crypto_hash_sha512_init(&state->ictx); crypto_hash_sha512_update(&state->ictx, key, keylen); crypto_hash_sha512_final(&state->ictx, khash); key = khash; keylen = 64; } crypto_hash_sha512_init(&state->ictx); memset(pad, 0x36, 128); for (i = 0; i < keylen; i++) { pad[i] ^= key[i]; } crypto_hash_sha512_update(&state->ictx, pad, 128); crypto_hash_sha512_init(&state->octx); memset(pad, 0x5c, 128); for (i = 0; i < keylen; i++) { pad[i] ^= key[i]; } crypto_hash_sha512_update(&state->octx, pad, 128); sodium_memzero((void *) pad, sizeof pad); sodium_memzero((void *) khash, sizeof khash); return 0; }
static int _blobcrypt_decrypt_flush(blobcrypt_decrypt_state *state) { block_ad ad; unsigned long long plen; size_t clen; assert(state->buf_pos > (sizeof state->nonce) + (sizeof state->auth)); clen = state->buf_pos - (sizeof state->nonce); _u64_le_from_ull(ad.offset, state->offset); memcpy(ad.message_id, state->message_id, sizeof ad.message_id); if (block_decrypt(state->buf, &plen, state->buf, clen, (unsigned char *) (void *) &ad, sizeof ad, state->message_id, state->nonce, state->k) != 0) { sodium_memzero(ad.message_id, sizeof ad.message_id); _blobcrypt_decrypt_sinkhole(state); return -1; } sodium_memzero(ad.message_id, sizeof ad.message_id); assert(plen == clen - (sizeof state->auth)); if (state->write_cb(state->user_ptr, state->buf, (size_t) plen) != 0) { _blobcrypt_decrypt_sinkhole(state); return -1; } assert(state->total_len >= plen); assert(state->offset <= state->total_len - plen); state->buf_pos = 0U; state->offset += plen; return 0; }
static void _blobcrypt_decrypt_sinkhole(blobcrypt_decrypt_state *state) { sodium_memzero(state->k, sizeof state->k); sodium_memzero(state->message_id, sizeof state->message_id); state->write_cb = _blobcrypt_decrypt_sinkhole_write_cb; }
int crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) { crypto_onetimeauth_poly1305_state state; unsigned char block0[64U]; unsigned char slen[8U]; unsigned char computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES]; unsigned long long mlen; int ret; (void) nsec; crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k); crypto_onetimeauth_poly1305_init(&state, block0); sodium_memzero(block0, sizeof block0); crypto_onetimeauth_poly1305_update(&state, ad, adlen); crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf); mlen = clen; crypto_onetimeauth_poly1305_update(&state, c, mlen); crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf); STORE64_LE(slen, (uint64_t) adlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); STORE64_LE(slen, (uint64_t) mlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); crypto_onetimeauth_poly1305_final(&state, computed_mac); sodium_memzero(&state, sizeof state); COMPILER_ASSERT(sizeof computed_mac == 16U); ret = crypto_verify_16(computed_mac, mac); sodium_memzero(computed_mac, sizeof computed_mac); if (m == NULL) { return ret; } if (ret != 0) { memset(m, 0, mlen); return -1; } crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k); return 0; }
int crypto_stream_salsa2012_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k) { unsigned char in[16]; unsigned char block[64]; unsigned char kcopy[32]; unsigned int i; unsigned int u; if (!mlen) { return 0; } for (i = 0; i < 32; ++i) { kcopy[i] = k[i]; } for (i = 0; i < 8; ++i) { in[i] = n[i]; } for (i = 8; i < 16; ++i) { in[i] = 0; } while (mlen >= 64) { crypto_core_salsa2012(block, in, kcopy, NULL); for (i = 0; i < 64; ++i) { c[i] = m[i] ^ block[i]; } u = 1; for (i = 8; i < 16; ++i) { u += (unsigned int)in[i]; in[i] = u; u >>= 8; } mlen -= 64; c += 64; m += 64; } if (mlen) { crypto_core_salsa2012(block, in, kcopy, NULL); for (i = 0; i < (unsigned int)mlen; ++i) { c[i] = m[i] ^ block[i]; } } sodium_memzero(block, sizeof block); sodium_memzero(kcopy, sizeof kcopy); return 0; }
static int stream_ref_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, uint64_t ic, const unsigned char *k) { unsigned char in[16]; unsigned char block[64]; unsigned char kcopy[32]; unsigned int i; unsigned int u; if (!mlen) { return 0; } for (i = 0; i < 32; i++) { kcopy[i] = k[i]; } for (i = 0; i < 8; i++) { in[i] = n[i]; } for (i = 8; i < 16; i++) { in[i] = (unsigned char) (ic & 0xff); ic >>= 8; } while (mlen >= 64) { crypto_core_salsa20(block, in, kcopy, NULL); for (i = 0; i < 64; i++) { c[i] = m[i] ^ block[i]; } u = 1; for (i = 8; i < 16; i++) { u += (unsigned int) in[i]; in[i] = u; u >>= 8; } mlen -= 64; c += 64; m += 64; } if (mlen) { crypto_core_salsa20(block, in, kcopy, NULL); for (i = 0; i < (unsigned int) mlen; i++) { c[i] = m[i] ^ block[i]; } } sodium_memzero(block, sizeof block); sodium_memzero(kcopy, sizeof kcopy); return 0; }
int encrypt(unsigned char* ciphertext, size_t* ciphertext_length, unsigned char* key) { unsigned char message[] = MESSAGE; printf("Message (%lu Bytes):\n%s\n\n", sizeof(message), message); //create random nonce unsigned char nonce[crypto_secretbox_NONCEBYTES]; randombytes_buf(nonce, crypto_secretbox_NONCEBYTES); //print nonce printf("Nonce (%i Bytes):\n", crypto_secretbox_NONCEBYTES); print_hex(nonce, crypto_secretbox_NONCEBYTES, 30); putchar('\n'); const unsigned char header[] = HEADER; printf("Header (%lu Bytes):\n%s\n\n", sizeof(header), header); int status = encrypt_message( ciphertext, ciphertext_length, message, sizeof(message), header, sizeof(header), nonce, key); sodium_memzero(message, sizeof(message)); return status; }
int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], const char * const passwd, unsigned long long passwdlen) { char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; escrypt_local_t escrypt_local; int ret = -1; if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) { return -1; } if (escrypt_init_local(&escrypt_local) != 0) { return -1; /* LCOV_EXCL_LINE */ } memset(wanted, 0, sizeof wanted); if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) str, (uint8_t *) wanted, sizeof wanted) == NULL) { escrypt_free_local(&escrypt_local); return -1; } escrypt_free_local(&escrypt_local); ret = sodium_memcmp(wanted, str, sizeof wanted); sodium_memzero(wanted, sizeof wanted); return ret; }
uint8_t * escrypt_r(escrypt_local_t *local, const uint8_t *passwd, size_t passwdlen, const uint8_t *setting, uint8_t *buf, size_t buflen) { uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES]; escrypt_kdf_t escrypt_kdf; const uint8_t *src; const uint8_t *salt; uint8_t *dst; size_t prefixlen; size_t saltlen; size_t need; uint64_t N; uint32_t N_log2; uint32_t r; uint32_t p; src = escrypt_parse_setting(setting, &N_log2, &r, &p); if (!src) { return NULL; } N = (uint64_t) 1 << N_log2; prefixlen = src - setting; salt = src; src = (uint8_t *) strrchr((char *) salt, '$'); if (src) { saltlen = src - salt; } else { saltlen = strlen((char *) salt); } need = prefixlen + saltlen + 1 + crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1; if (need > buflen || need < saltlen) { return NULL; } #ifdef HAVE_EMMINTRIN_H escrypt_kdf = sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse; #else escrypt_kdf = escrypt_kdf_nosse; #endif if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen, N, r, p, hash, sizeof(hash))) { return NULL; } dst = buf; memcpy(dst, setting, prefixlen + saltlen); dst += prefixlen + saltlen; *dst++ = '$'; dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash)); sodium_memzero(hash, sizeof hash); if (!dst || dst >= buf + buflen) { return NULL; /* Can't happen LCOV_EXCL_LINE */ } *dst = 0; /* NUL termination */ return buf; }
int balloc(buffer_t *ptr, size_t capacity) { sodium_memzero(ptr, sizeof(buffer_t)); ptr->array = ss_malloc(capacity); ptr->capacity = capacity; return capacity; }
/* Same as above, except with use the given salt for deterministic key derivation. * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ bool tox_pass_key_derive_with_salt(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength, const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error) { if (!salt || !out_key || (!passphrase && pplength != 0)) { SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); return 0; } uint8_t passkey[crypto_hash_sha256_BYTES]; crypto_hash_sha256(passkey, passphrase, pplength); uint8_t key[CRYPTO_SHARED_KEY_SIZE]; /* Derive a key from the password */ /* http://doc.libsodium.org/key_derivation/README.html */ /* note that, according to the documentation, a generic pwhash interface will be created * once the pwhash competition (https://password-hashing.net/) is over */ if (crypto_pwhash_scryptsalsa208sha256( key, sizeof(key), (char *)passkey, sizeof(passkey), salt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory most likely */ SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); return 0; } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); memcpy(out_key->key, key, CRYPTO_SHARED_KEY_SIZE); SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); return 1; }
int main(void) { void *buf; size_t size; #ifdef SIGSEGV signal(SIGSEGV, segv_handler); #endif #ifdef SIGBUS signal(SIGBUS, segv_handler); #endif #ifdef SIGABRT signal(SIGABRT, segv_handler); #endif size = 1U + randombytes_uniform(100000U); buf = sodium_malloc(size); assert(buf != NULL); sodium_mprotect_noaccess(buf); sodium_mprotect_readwrite(buf); #ifndef __EMSCRIPTEN__ sodium_memzero(((unsigned char *)buf) - 8, 8U); sodium_mprotect_readonly(buf); sodium_free(buf); printf("Underflow not caught\n"); #endif return 0; }
static int do_incoming(TCP_Server *TCP_server, uint32_t i) { if (TCP_server->incomming_connection_queue[i].status != TCP_STATUS_CONNECTED) { return -1; } int ret = read_connection_handshake(&TCP_server->incomming_connection_queue[i], TCP_server->secret_key); if (ret == -1) { kill_TCP_connection(&TCP_server->incomming_connection_queue[i]); } else if (ret == 1) { int index_new = TCP_server->unconfirmed_connection_queue_index % MAX_INCOMMING_CONNECTIONS; TCP_Secure_Connection *conn_old = &TCP_server->incomming_connection_queue[i]; TCP_Secure_Connection *conn_new = &TCP_server->unconfirmed_connection_queue[index_new]; if (conn_new->status != TCP_STATUS_NO_STATUS) { kill_TCP_connection(conn_new); } memcpy(conn_new, conn_old, sizeof(TCP_Secure_Connection)); sodium_memzero(conn_old, sizeof(TCP_Secure_Connection)); ++TCP_server->unconfirmed_connection_queue_index; return index_new; } return -1; }
int _crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *sk, int prehashed) { crypto_hash_sha512_state hs; unsigned char az[64]; unsigned char nonce[64]; unsigned char hram[64]; ge_p3 R; _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); #ifdef ED25519_NONDETERMINISTIC memcpy(az, sk, 32); _crypto_sign_ed25519_synthetic_r_hv(&hs, nonce, az); #else crypto_hash_sha512(az, sk, 32); crypto_hash_sha512_update(&hs, az + 32, 32); #endif crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, nonce); memmove(sig + 32, sk + 32, 32); sc_reduce(nonce); ge_scalarmult_base(&R, nonce); ge_p3_tobytes(sig, &R); _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); crypto_hash_sha512_update(&hs, sig, 64); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, hram); sc_reduce(hram); _crypto_sign_ed25519_clamp(az); sc_muladd(sig + 32, hram, az, nonce); sodium_memzero(az, sizeof az); sodium_memzero(nonce, sizeof nonce); if (siglen_p != NULL) { *siglen_p = 64U; } return 0; }
int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen, const unsigned char *m, unsigned long long mlen, const unsigned char *sk) { crypto_hash_sha512_state hs; unsigned char pk[32]; unsigned char az[64]; unsigned char nonce[64]; unsigned char hram[64]; ge_p3 R; memmove(pk, sk + 32, 32); crypto_hash_sha512(az, sk, 32); az[0] &= 248; az[31] &= 63; az[31] |= 64; crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, az + 32, 32); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, nonce); memmove(sig + 32, pk, 32); sc_reduce(nonce); ge_scalarmult_base(&R, nonce); ge_p3_tobytes(sig, &R); crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, sig, 64); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, hram); sc_reduce(hram); sc_muladd(sig + 32, hram, az, nonce); sodium_memzero(az, sizeof az); sodium_memzero(nonce, sizeof nonce); if (siglen != NULL) { *siglen = 64U; } return 0; }
int main(void) { unsigned char buf1[1000]; unsigned char buf2[1000]; randombytes(buf1, sizeof buf1); memcpy(buf2, buf1, sizeof buf2); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, 0U); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, sizeof buf1 / 2); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf ("%d\n", sodium_memcmp(buf1, buf2, 0U)); sodium_memzero(buf2, sizeof buf2 / 2); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); return 0; }
int hkdf_derive_secrets_nosalt(unsigned char* out, enum hkdf_msg_ver_t offset, const unsigned char* in, const size_t inlen, const unsigned char* info, const size_t infolen, const unsigned outlen) { unsigned char salt[HASH_OUTSZ]; sodium_memzero(salt, sizeof salt); return hkdf_derive_secrets(out, offset, in, inlen, salt, sizeof salt, info, infolen, outlen); }
void enc_ctx_init(int method, enc_ctx_t *ctx, int enc) { sodium_memzero(ctx, sizeof(enc_ctx_t)); cipher_context_init(&ctx->evp, method, enc); if (enc) { rand_bytes(ctx->evp.iv, enc_iv_len); } }
static int stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k) { unsigned char in[16]; unsigned char block[64]; unsigned char kcopy[32]; unsigned int i; unsigned int u; if (!clen) { return 0; } for (i = 0; i < 32; i++) { kcopy[i] = k[i]; } for (i = 0; i < 8; i++) { in[i] = n[i]; } for (i = 8; i < 16; i++) { in[i] = 0; } while (clen >= 64) { crypto_core_salsa20(c, in, kcopy, NULL); u = 1; for (i = 8; i < 16; i++) { u += (unsigned int) in[i]; in[i] = u; u >>= 8; } clen -= 64; c += 64; } if (clen) { crypto_core_salsa20(block, in, kcopy, NULL); for (i = 0; i < (unsigned int) clen; i++) { c[i] = block[i]; } } sodium_memzero(block, sizeof block); sodium_memzero(kcopy, sizeof kcopy); return 0; }
int crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) { crypto_onetimeauth_poly1305_state state; unsigned char block0[64U]; unsigned char slen[8U]; (void) nsec; crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k); crypto_onetimeauth_poly1305_init(&state, block0); sodium_memzero(block0, sizeof block0); crypto_onetimeauth_poly1305_update(&state, ad, adlen); crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf); crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k); crypto_onetimeauth_poly1305_update(&state, c, mlen); crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf); STORE64_LE(slen, (uint64_t) adlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); STORE64_LE(slen, (uint64_t) mlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); crypto_onetimeauth_poly1305_final(&state, mac); sodium_memzero(&state, sizeof state); if (maclen_p != NULL) { *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES; } return 0; }
// Derives the Ed25519 public key from the stored private key seed. int EdDSA::publicKey(unsigned char* pubKey) { unsigned char privKey[crypto_sign_SECRETKEYBYTES]; int check = crypto_sign_seed_keypair(pubKey, privKey, (const unsigned char*)this->keySeed); sodium_memzero(privKey, sizeof privKey); if (check != 0) { return(0); } return(1); }
/* * Call this function after trying to decrypt a message and pass it if * the decryption was successful or if it wasn't. */ int ratchet_set_last_message_authenticity(ratchet_state *state, bool valid) { //prepare for being able to receive new messages state->received_valid = true; //backup header decryptability ratchet_header_decryptability header_decryptable = state->header_decryptable; state->header_decryptable = NOT_TRIED; //TODO make sure this function aborts if it is called at the wrong time int status; //TODO I can do those if's better. This only happens to be this way because of the specification if ((!is_none(state->receive_header_key, crypto_aead_chacha20poly1305_KEYBYTES)) && (header_decryptable == CURRENT_DECRYPTABLE)) { //still the same message chain //if HKr != <none> and Dec(HKr, header) if (!valid) { //message couldn't be decrypted //clear purported message and header keys header_and_message_keystore_clear(&(state->purported_header_and_message_keys)); return 0; //TODO: Should this really be 0? } } else { //new message chain if (state->ratchet_flag || (header_decryptable != NEXT_DECRYPTABLE) || !valid) { //if ratchet_flag or not Dec(NHKr, header) //clear purported message and header keys header_and_message_keystore_clear(&(state->purported_header_and_message_keys)); return 0; //TODO: Should this really be 0? } //otherwise, received message was valid //accept purported values //RK = RKp memcpy(state->root_key, state->purported_root_key, crypto_secretbox_KEYBYTES); //HKr = HKp memcpy(state->receive_header_key, state->purported_receive_header_key, sizeof(state->receive_header_key)); //NHKr = NHKp memcpy(state->next_receive_header_key, state->purported_next_receive_header_key, sizeof(state->next_receive_header_key)); //DHRr = DHRp memcpy(state->their_public_ephemeral, state->their_purported_public_ephemeral, crypto_box_PUBLICKEYBYTES); //erase(DHRs) sodium_memzero(state->our_private_ephemeral, crypto_box_SECRETKEYBYTES); //ratchet_flag = True state->ratchet_flag = true; } status = commit_skipped_header_and_message_keys(state); if (status != 0) { return status; } //Nr = Np + 1 state->receive_message_number = state->purported_message_number + 1; //CKr = CKp memcpy(state->receive_chain_key, state->purported_receive_chain_key, crypto_secretbox_KEYBYTES); return 0; }
int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { unsigned char seed[32]; int ret; randombytes_buf(seed, sizeof seed); ret = crypto_sign_seed_keypair(pk, sk, seed); sodium_memzero(seed, sizeof seed); return ret; }
void stream_ctx_init(cipher_t *cipher, cipher_ctx_t *cipher_ctx, int enc) { sodium_memzero(cipher_ctx, sizeof(cipher_ctx_t)); stream_cipher_ctx_init(cipher_ctx, cipher->method, enc); cipher_ctx->cipher = cipher; if (enc) { rand_bytes(cipher_ctx->nonce, cipher->nonce_len); } }
int main(void) { void *buf; size_t size; unsigned int i; if (sodium_malloc(SIZE_MAX - 1U) != NULL) { return 1; } if (sodium_allocarray(SIZE_MAX / 2U + 1U, SIZE_MAX / 2U) != NULL) { return 1; } sodium_free(sodium_allocarray(0U, 0U)); sodium_free(sodium_allocarray(0U, 1U)); sodium_free(sodium_allocarray(1U, 0U)); buf = sodium_allocarray(1000U, 50U); memset(buf, 0, 50000U); sodium_free(buf); sodium_free(sodium_malloc(0U)); sodium_free(NULL); for (i = 0U; i < 10000U; i++) { size = randombytes_uniform(100000U); buf = sodium_malloc(size); assert(buf != NULL); memset(buf, i, size); sodium_mprotect_noaccess(buf); sodium_free(buf); } printf("OK\n"); #ifdef SIGSEGV signal(SIGSEGV, segv_handler); #endif #ifdef SIGBUS signal(SIGBUS, segv_handler); #endif #ifdef SIGABRT signal(SIGABRT, segv_handler); #endif size = randombytes_uniform(100000U); buf = sodium_malloc(size); assert(buf != NULL); sodium_mprotect_readonly(buf); sodium_mprotect_readwrite(buf); #ifndef __EMSCRIPTEN__ sodium_memzero(((unsigned char *)buf) + size, 1U); sodium_mprotect_noaccess(buf); sodium_free(buf); printf("Overflow not caught\n"); #endif return 0; }
ClientConfiguration::BackupData ClientConfiguration::fromBackup(QString const& backup, QString const& password) { QByteArray decodedBase32 = Base32::decodeBase32Sequence(backup); if (decodedBase32.size() != BACKUP_DECODED_BYTES) { throw IllegalArgumentException() << "Invalid Backup: Size of decoded Backup String is incorrect (" << decodedBase32.size() << " Bytes instead of " << BACKUP_DECODED_BYTES << " Bytes)."; } unsigned char encryptionKey[BACKUP_ENCRYPTION_KEY_BYTES]; sodium_memzero(encryptionKey, BACKUP_ENCRYPTION_KEY_BYTES); // The pointer to the base32-decoded Backup unsigned char* decodedBase32Ptr = reinterpret_cast<unsigned char*>(decodedBase32.data()); // The Salt used in the PBKDF2 Key Derivation process is embedded in the first 8 bytes of the Backup. QByteArray password8Bit = password.toUtf8(); PKCS5_PBKDF2_HMAC(reinterpret_cast<unsigned char*>(password8Bit.data()), password8Bit.size(), decodedBase32Ptr, BACKUP_SALT_BYTES, BACKUP_KEY_PBKDF_ITERATIONS, BACKUP_ENCRYPTION_KEY_BYTES, encryptionKey); unsigned char nonceBytes[crypto_stream_NONCEBYTES]; sodium_memzero(nonceBytes, crypto_stream_NONCEBYTES); crypto_stream_xor(&decodedBase32Ptr[BACKUP_SALT_BYTES], &decodedBase32Ptr[BACKUP_SALT_BYTES], BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES, nonceBytes, encryptionKey); // The last two bytes of the Backup contain the truncated SHA-256 Hash over the identity and its Private Key. unsigned char controlHash[crypto_hash_sha256_BYTES]; sodium_memzero(controlHash, crypto_hash_sha256_BYTES); crypto_hash_sha256(controlHash, &(decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES); if (sodium_memcmp(&(decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES]), controlHash, BACKUP_HASH_BYTES) != 0) { throw IllegalArgumentException() << "Decryption of Backup failed: Invalid Control Hash (" << controlHash[0] << controlHash[1] << " vs. " << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES] << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + 1] << ")."; } unsigned char derivedPublicKey[PROTO_KEY_LENGTH_BYTES]; crypto_scalarmult_base(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); KeyPair kp = KeyPair::fromArrays(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); QString identityString(QByteArray(reinterpret_cast<char*>(&decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES)); if (!isValidIdentity(identityString)) { throw IllegalArgumentException() << "Invalid ClientConfiguration: Decryption of Backup failed: Not a valid Identity."; } return BackupData(ContactId(identityString.toUtf8()), kp); }
int crypto_stream_salsa2012( unsigned char *c,unsigned long long clen, const unsigned char *n, const unsigned char *k ) { unsigned char in[16]; unsigned char block[64]; unsigned char kcopy[32]; unsigned int i; unsigned int u; if (!clen) return 0; for (i = 0;i < 32;++i) kcopy[i] = k[i]; for (i = 0;i < 8;++i) in[i] = n[i]; for (i = 8;i < 16;++i) in[i] = 0; while (clen >= 64) { crypto_core_salsa2012(c,in,kcopy,sigma); u = 1; for (i = 8;i < 16;++i) { u += (unsigned int) in[i]; in[i] = u; u >>= 8; } clen -= 64; c += 64; } if (clen) { crypto_core_salsa2012(block,in,kcopy,sigma); for (i = 0;i < (unsigned int) clen;++i) c[i] = block[i]; } sodium_memzero(block, sizeof block); sodium_memzero(kcopy, sizeof kcopy); return 0; }
void aead_ctx_init(cipher_t *cipher, cipher_ctx_t *cipher_ctx, int enc) { sodium_memzero(cipher_ctx, sizeof(cipher_ctx_t)); cipher_ctx->cipher = cipher; aead_cipher_ctx_init(cipher_ctx, cipher->method, enc); if (enc) { rand_bytes(cipher_ctx->salt, cipher->key_len); } }
int main(void) { unsigned char buf1[1000]; unsigned char buf2[1000]; char buf3[33]; randombytes(buf1, sizeof buf1); memcpy(buf2, buf1, sizeof buf2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, 0U); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, sizeof buf1 / 2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf("%d\n", sodium_memcmp(buf1, buf2, 0U)); sodium_memzero(buf2, sizeof buf2 / 2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf("%s\n", sodium_bin2hex(buf3, 33U, (const unsigned char *) "0123456789ABCDEF", 16U)); return 0; }