int main(void) { if (sodium_init() == -1) { return -1; } return_status status = return_status_init(); //create buffers buffer_t *master_key = buffer_create_on_heap(50, 50); buffer_t *subkey1 = buffer_create_on_heap(60, 60); buffer_t *subkey2 = buffer_create_on_heap(60, 60); buffer_t *subkey1_copy = buffer_create_on_heap(60, 60); int status_int = 0; status_int = buffer_fill_random(master_key, master_key->buffer_length); if (status_int != 0) { throw(KEYDERIVATION_FAILED, "Failed to generate master key."); } printf("Master key:\n"); print_hex(master_key); putchar('\n'); status = derive_key(subkey1, subkey1->buffer_length, master_key, 0); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive first subkey."); printf("First subkey:\n"); print_hex(subkey1); putchar('\n'); status = derive_key(subkey2, subkey2->buffer_length, master_key, 1); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive the second subkey."); printf("Second subkey:\n"); print_hex(subkey2); putchar('\n'); if (buffer_compare(subkey1, subkey2) == 0) { throw(KEYGENERATION_FAILED, "Both subkeys are the same."); } status = derive_key(subkey1_copy, subkey1_copy->buffer_length, master_key, 0); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive copy of the first subkey."); if (buffer_compare(subkey1, subkey1_copy) != 0) { throw(INCORRECT_DATA, "Failed to reproduce subkey."); } cleanup: buffer_destroy_from_heap_and_null_if_valid(master_key); buffer_destroy_from_heap_and_null_if_valid(subkey1); buffer_destroy_from_heap_and_null_if_valid(subkey2); buffer_destroy_from_heap_and_null_if_valid(subkey1_copy); on_error { print_errors(&status); } return_status_destroy_errors(&status); return status.status; }
//! Use key + salt to encrypt the header, and write it to disk. status_t VolumeCryptContext::_WriteHeader(int fd, const uint8* key, uint32 keyLength, off_t headerOffset, uint8* buffer) { uint8 diskKey[DISK_KEY_SIZE]; derive_key(key, keyLength, buffer, PKCS5_SALT_SIZE, diskKey, DISK_KEY_SIZE); status_t status = Init(ALGORITHM_AES, MODE_XTS, diskKey, DISK_KEY_SIZE); if (status != B_OK) return status; true_crypt_header& header = *(true_crypt_header*)&buffer[PKCS5_SALT_SIZE]; Encrypt((uint8*)&header, BLOCK_SIZE - PKCS5_SALT_SIZE); ssize_t bytesWritten = write_pos(fd, headerOffset, buffer, BLOCK_SIZE); if (bytesWritten < 0) return errno; // use the decrypted header to init the volume encryption Decrypt((uint8*)&header, BLOCK_SIZE - PKCS5_SALT_SIZE); SetKey(header.disk_key, sizeof(header.disk_key)); return B_OK; }
int kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, const u_char *shared_secret, u_int slen) { struct kex *kex = ssh->kex; u_char *keys[NKEYS]; u_int i, j, mode, ctos; int r; for (i = 0; i < NKEYS; i++) { if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen, shared_secret, slen, &keys[i])) != 0) { for (j = 0; j < i; j++) free(keys[j]); return r; } } for (mode = 0; mode < MODE_MAX; mode++) { ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1]; kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; } return 0; }
/** * gcr_secret_exchange_receive: * @self: a #GcrSecretExchange object * @exchange: the string received * * Receive a string from the other side of secret exchange. This string will * have been created by gcr_secret_exchange_begin() or gcr_secret_exchange_send(). * * After this call completes successfully the value returned from * gcr_secret_exchange_get_secret() will have changed. * * Returns: whether the string was successfully parsed and received */ gboolean gcr_secret_exchange_receive (GcrSecretExchange *self, const gchar *exchange) { GcrSecretExchangeClass *klass; gchar *secret = NULL; gsize n_secret = 0; GKeyFile *input; gboolean ret; g_return_val_if_fail (GCR_IS_SECRET_EXCHANGE (self), FALSE); g_return_val_if_fail (exchange != NULL, FALSE); klass = GCR_SECRET_EXCHANGE_GET_CLASS (self); g_return_val_if_fail (klass->generate_exchange_key, FALSE); g_return_val_if_fail (klass->derive_transport_key, FALSE); gchar *string = g_strescape (exchange, ""); g_debug ("receiving secret exchange: %s", string); g_free (string); /* Parse the input */ input = g_key_file_new (); if (!g_key_file_load_from_data (input, exchange, strlen (exchange), G_KEY_FILE_NONE, NULL)) { g_key_file_free (input); g_message ("couldn't parse secret exchange data"); return FALSE; } if (!self->pv->generated) { if (!(klass->generate_exchange_key) (self, GCR_SECRET_EXCHANGE_PROTOCOL_1, &self->pv->publi, &self->pv->n_publi)) g_return_val_if_reached (FALSE); self->pv->generated = TRUE; } ret = TRUE; if (!self->pv->derived) { if (!derive_key (self, input)) ret = FALSE; } if (ret && g_key_file_has_key (input, GCR_SECRET_EXCHANGE_PROTOCOL_1, "secret", NULL)) ret = perform_decrypt (self, input, (guchar **)&secret, &n_secret); if (ret) { egg_secure_free (self->pv->secret); self->pv->secret = secret; self->pv->n_secret = n_secret; } g_key_file_free (input); return ret; }
sgx_status_t key_derivation(const sgx_ec256_dh_shared_t* shared_key, uint16_t kdf_id, sgx_ec_key_128bit_t* smk_key, sgx_ec_key_128bit_t* sk_key, sgx_ec_key_128bit_t* mk_key, sgx_ec_key_128bit_t* vk_key) { bool derive_ret = false; if (NULL == shared_key) { return SGX_ERROR_INVALID_PARAMETER; } if (ISV_KDF_ID != kdf_id) { //fprintf(stderr, "\nError, key derivation id mismatch in [%s].", __FUNCTION__); return SGX_ERROR_KDF_MISMATCH; } derive_ret = derive_key(shared_key, DERIVE_KEY_SMK_SK, smk_key, sk_key); if (derive_ret != true) { //fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); return SGX_ERROR_UNEXPECTED; } derive_ret = derive_key(shared_key, DERIVE_KEY_MK_VK, mk_key, vk_key); if (derive_ret != true) { //fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); return SGX_ERROR_UNEXPECTED; } return SGX_SUCCESS; }
static void crypt_all(int count) { int index = 0; #ifdef _OPENMP #pragma omp parallel for for (index = 0; index < count; index++) #endif { unsigned char master[24]; derive_key((unsigned char *)saved_key[index], strlen(saved_key[index]), salt_struct->salt, SALTLEN, 1000, master, 24); if(kcdecrypt(master, salt_struct->iv, salt_struct->ct) == 0) cracked[index] = 1; else cracked[index] = 0; } }
static void crypt_all(int count) { int index; #ifdef _OPENMP #pragma omp parallel for default(none) private(index) shared(count, passverify, has_been_cracked, saved_key, saved_salt, mode) #endif for (index = 0; index < count; index++) { unsigned char pwd_ver[2] = { 0 }; unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH]; /* Derive the encryption and authetication keys and the password verifier */ derive_key((unsigned char *)saved_key[index], strlen(saved_key[index]), saved_salt, SALT_LENGTH(mode), KEYING_ITERATIONS, kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH); has_been_cracked[index] = !memcmp(pwd_ver, passverify, 2); } }
int fcrypt_init( int mode, /* the mode to be used (input) */ const unsigned char pwd[], /* the user specified password (input) */ unsigned int pwd_len, /* the length of the password (input) */ const unsigned char salt[], /* the salt (input) */ #ifdef PASSWORD_VERIFIER unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ #endif fcrypt_ctx cx[1]) /* the file encryption context (output) */ { unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH]; if(pwd_len > MAX_PWD_LENGTH) return PASSWORD_TOO_LONG; if(mode < 1 || mode > 3) return BAD_MODE; cx->mode = mode; cx->pwd_len = pwd_len; /* initialise the encryption nonce and buffer pos */ cx->encr_pos = BLOCK_SIZE; /* if we need a random component in the encryption */ /* nonce, this is where it would have to be set */ memset(cx->nonce, 0, BLOCK_SIZE * sizeof(unsigned char)); /* initialise for authentication */ hmac_sha_begin(cx->auth_ctx); /* derive the encryption and authetication keys and the password verifier */ derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS, kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); /* set the encryption key */ aes_encrypt_key(kbuf, KEY_LENGTH(mode), cx->encr_ctx); /* set the authentication key */ hmac_sha_key(kbuf + KEY_LENGTH(mode), KEY_LENGTH(mode), cx->auth_ctx); #ifdef PASSWORD_VERIFIER memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH); #endif /* clear the buffer holding the derived key values */ memset(kbuf, 0, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); return GOOD_RETURN; }
void kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) { u_char *keys[NKEYS]; int i, mode, ctos; for (i = 0; i < NKEYS; i++) keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); debug2("kex_derive_keys"); for (mode = 0; mode < MODE_MAX; mode++) { current_keys[mode] = kex->newkeys[mode]; kex->newkeys[mode] = NULL; ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; } }
int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, const char *params) { uint8_t buf[30]; ff_srtp_free(s); // RFC 4568 if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80") || !strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_80")) { s->rtp_hmac_size = s->rtcp_hmac_size = 10; } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) { s->rtp_hmac_size = s->rtcp_hmac_size = 4; } else if (!strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_32")) { // RFC 5764 section 4.1.2 s->rtp_hmac_size = 4; s->rtcp_hmac_size = 10; } else { av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n", suite); return AVERROR(EINVAL); } if (av_base64_decode(buf, params, sizeof(buf)) != sizeof(buf)) { av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n"); return AVERROR(EINVAL); } // MKI and lifetime not handled yet s->aes = av_aes_alloc(); s->hmac = av_hmac_alloc(AV_HMAC_SHA1); if (!s->aes || !s->hmac) return AVERROR(ENOMEM); memcpy(s->master_key, buf, 16); memcpy(s->master_salt, buf + 16, 14); // RFC 3711 av_aes_init(s->aes, s->master_key, 128, 0); derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key)); derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt)); derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth)); derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key)); derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt)); derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth)); return 0; }
secure_vector<uint8_t> pbes2_decrypt(const secure_vector<uint8_t>& key_bits, const std::string& passphrase, const std::vector<uint8_t>& params) { AlgorithmIdentifier kdf_algo, enc_algo; BER_Decoder(params) .start_cons(SEQUENCE) .decode(kdf_algo) .decode(enc_algo) .end_cons(); const std::string cipher = OIDS::lookup(enc_algo.get_oid()); const std::vector<std::string> cipher_spec = split_on(cipher, '/'); if(cipher_spec.size() != 2) throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); if(!known_pbes_cipher_mode(cipher_spec[1])) throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); secure_vector<uint8_t> iv; BER_Decoder(enc_algo.get_parameters()).decode(iv, OCTET_STRING).verify_end(); std::unique_ptr<Cipher_Mode> dec = Cipher_Mode::create(cipher, DECRYPTION); if(!dec) throw Decoding_Error("PBE-PKCS5 cannot decrypt no cipher " + cipher); dec->set_key(derive_key(passphrase, kdf_algo, dec->key_spec().maximum_keylength())); dec->start(iv); secure_vector<uint8_t> buf = key_bits; dec->finish(buf); return buf; }
int zfs_crypto_load_key(zfs_handle_t *zhp, boolean_t noop, char *alt_keylocation) { int ret, attempts = 0; char errbuf[1024]; uint64_t keystatus, iters = 0, salt = 0; uint64_t keyformat = ZFS_KEYFORMAT_NONE; char prop_keylocation[MAXNAMELEN]; char prop_encroot[MAXNAMELEN]; char *keylocation = NULL; uint8_t *key_material = NULL, *key_data = NULL; size_t key_material_len; boolean_t is_encroot, can_retry = B_FALSE, correctible = B_FALSE; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "Key load error")); /* check that encryption is enabled for the pool */ if (!encryption_feature_is_enabled(zhp->zpool_hdl)) { zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Encryption feature not enabled.")); ret = EINVAL; goto error; } /* Fetch the keyformat. Check that the dataset is encrypted. */ keyformat = zfs_prop_get_int(zhp, ZFS_PROP_KEYFORMAT); if (keyformat == ZFS_KEYFORMAT_NONE) { zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "'%s' is not encrypted."), zfs_get_name(zhp)); ret = EINVAL; goto error; } /* * Fetch the key location. Check that we are working with an * encryption root. */ ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, prop_encroot); if (ret != 0) { zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Failed to get encryption root for '%s'."), zfs_get_name(zhp)); goto error; } else if (!is_encroot) { zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Keys must be loaded for encryption root of '%s' (%s)."), zfs_get_name(zhp), prop_encroot); ret = EINVAL; goto error; } /* * if the caller has elected to override the keylocation property * use that instead */ if (alt_keylocation != NULL) { keylocation = alt_keylocation; } else { ret = zfs_prop_get(zhp, ZFS_PROP_KEYLOCATION, prop_keylocation, sizeof (prop_keylocation), NULL, NULL, 0, B_TRUE); if (ret != 0) { zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Failed to get keylocation for '%s'."), zfs_get_name(zhp)); goto error; } keylocation = prop_keylocation; } /* check that the key is unloaded unless this is a noop */ if (!noop) { keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); if (keystatus == ZFS_KEYSTATUS_AVAILABLE) { zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Key already loaded for '%s'."), zfs_get_name(zhp)); ret = EEXIST; goto error; } } /* passphrase formats require a salt and pbkdf2_iters property */ if (keyformat == ZFS_KEYFORMAT_PASSPHRASE) { salt = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_SALT); iters = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_ITERS); } try_again: /* fetching and deriving the key are correctible errors. set the flag */ correctible = B_TRUE; /* get key material from key format and location */ ret = get_key_material(zhp->zfs_hdl, B_FALSE, B_FALSE, keyformat, keylocation, zfs_get_name(zhp), &key_material, &key_material_len, &can_retry); if (ret != 0) goto error; /* derive a key from the key material */ ret = derive_key(zhp->zfs_hdl, keyformat, iters, key_material, key_material_len, salt, &key_data); if (ret != 0) goto error; correctible = B_FALSE; /* pass the wrapping key and noop flag to the ioctl */ ret = lzc_load_key(zhp->zfs_name, noop, key_data, WRAPPING_KEY_LEN); if (ret != 0) { switch (ret) { case EPERM: zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Permission denied.")); break; case EINVAL: zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Invalid parameters provided for dataset %s."), zfs_get_name(zhp)); break; case EEXIST: zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Key already loaded for '%s'."), zfs_get_name(zhp)); break; case EBUSY: zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "'%s' is busy."), zfs_get_name(zhp)); break; case EACCES: correctible = B_TRUE; zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, "Incorrect key provided for '%s'."), zfs_get_name(zhp)); break; } goto error; } free(key_material); free(key_data); return (0); error: zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); if (key_material != NULL) free(key_material); if (key_data != NULL) free(key_data); /* * Here we decide if it is ok to allow the user to retry entering their * key. The can_retry flag will be set if the user is entering their * key from an interactive prompt. The correctible flag will only be * set if an error that occured could be corrected by retrying. Both * flags are needed to allow the user to attempt key entry again */ if (can_retry && correctible && attempts <= MAX_KEY_PROMPT_ATTEMPTS) { attempts++; goto try_again; } return (ret); }
status_t VolumeCryptContext::_Detect(int fd, off_t offset, off_t size, const uint8* key, uint32 keyLength, uint8* buffer, true_crypt_header& header) { ssize_t bytesRead = read_pos(fd, offset, buffer, BLOCK_SIZE); if (bytesRead != BLOCK_SIZE) return bytesRead < 0 ? errno : B_IO_ERROR; // decrypt header first uint8* encryptedHeader = buffer + PKCS5_SALT_SIZE; uint8* salt = buffer; uint8 diskKey[DISK_KEY_SIZE]; derive_key(key, keyLength, salt, PKCS5_SALT_SIZE, diskKey, DISK_KEY_SIZE); //dprintf("salt %x, key %x\n", *(int*)salt, *(int*)diskKey); status_t status = Init(ALGORITHM_AES, MODE_XTS, diskKey, DISK_KEY_SIZE); if (status != B_OK) return status; memcpy(&header, encryptedHeader, sizeof(true_crypt_header)); Decrypt((uint8*)&header, sizeof(true_crypt_header)); if (!valid_true_crypt_header(header)) { dump_true_crypt_header(header); // Try with legacy encryption mode LRW instead status = Init(ALGORITHM_AES, MODE_LRW, diskKey, DISK_KEY_SIZE); if (status != B_OK) return status; memcpy(&header, encryptedHeader, sizeof(true_crypt_header)); Decrypt((uint8*)&header, sizeof(true_crypt_header)); if (!valid_true_crypt_header(header)) { dump_true_crypt_header(header); return B_PERMISSION_DENIED; } } if (header.RequiredProgramVersion() >= 0x700) { // TODO: test if the block size is really not 512 bytes dprintf("header version not yet supported!\n"); return B_NOT_SUPPORTED; } // then init context with the keys from the unencrypted header SetKey(header.disk_key, sizeof(header.disk_key)); if (offset != 0) { // this is a hidden drive, take over the size from the header fSize = B_BENDIAN_TO_HOST_INT64(header.hidden_size); fOffset = offset - fSize; fHidden = true; } else { fOffset = BLOCK_SIZE; fSize = size - BLOCK_SIZE; fHidden = false; } if (header.Version() >= 4) { fOffset = header.EncryptedOffset(); fSize = header.EncryptedSize(); } fMode->SetBlockOffset(fOffset / BLOCK_SIZE); return B_OK; }
int nterfacer_line_event(struct esocket *sock, char *newline) { struct sconnect *socket = sock->tag; char *response, *theirnonceh = NULL, *theirivh = NULL; unsigned char theirnonce[16], theiriv[16]; int number, reason; switch(socket->status) { case SS_IDLE: if(strcasecmp(newline, ANTI_FULL_VERSION)) { nterface_log(nrl, NL_INFO, "Protocol mismatch from %s: %s", socket->permit->hostname->content, newline); return 1; } else { unsigned char challenge[32]; char ivhex[16 * 2 + 1], noncehex[16 * 2 + 1]; if(!get_entropy(challenge, 32) || !get_entropy(socket->iv, 16)) { nterface_log(nrl, NL_ERROR, "Unable to open challenge/IV entropy bin!"); return 1; } int_to_hex(challenge, socket->challenge, 32); int_to_hex(socket->iv, ivhex, 16); memcpy(socket->response, challenge_response(socket->challenge, socket->permit->password->content), sizeof(socket->response)); socket->response[sizeof(socket->response) - 1] = '\0'; /* just in case */ socket->status = SS_VERSIONED; if(!generate_nonce(socket->ournonce, 1)) { nterface_log(nrl, NL_ERROR, "Unable to generate nonce!"); return 1; } int_to_hex(socket->ournonce, noncehex, 16); if(esocket_write_line(sock, "%s %s %s", socket->challenge, ivhex, noncehex)) return BUF_ERROR; return 0; } break; case SS_VERSIONED: for(response=newline;*response;response++) { if((*response == ' ') && (*(response + 1))) { *response = '\0'; theirivh = response + 1; break; } } if(theirivh) { for(response=theirivh;*response;response++) { if((*response == ' ') && (*(response + 1))) { *response = '\0'; theirnonceh = response + 1; break; } } } if(!theirivh || (strlen(theirivh) != 32) || !hex_to_int(theirivh, theiriv, sizeof(theiriv)) || !theirnonceh || (strlen(theirnonceh) != 32) || !hex_to_int(theirnonceh, theirnonce, sizeof(theirnonce))) { nterface_log(nrl, NL_INFO, "Protocol error drop: %s", socket->permit->hostname->content); return 1; } if(!memcmp(socket->ournonce, theirnonce, sizeof(theirnonce))) { nterface_log(nrl, NL_INFO, "Bad nonce drop: %s", socket->permit->hostname->content); return 1; } if(!strncasecmp(newline, socket->response, sizeof(socket->response))) { unsigned char theirkey[32], ourkey[32]; derive_key(ourkey, socket->permit->password->content, socket->challenge, socket->ournonce, theirnonce, (unsigned char *)"SERVER", 6); derive_key(theirkey, socket->permit->password->content, socket->response, theirnonce, socket->ournonce, (unsigned char *)"CLIENT", 6); nterface_log(nrl, NL_INFO, "Authed: %s", socket->permit->hostname->content); socket->status = SS_AUTHENTICATED; switch_buffer_mode(sock, ourkey, socket->iv, theirkey, theiriv); if(esocket_write_line(sock, "Oauth")) return BUF_ERROR; } else { nterface_log(nrl, NL_INFO, "Bad CR drop: %s", socket->permit->hostname->content); return 1; } break; case SS_AUTHENTICATED: nterface_log(nrl, NL_INFO|NL_LOG_ONLY, "L(%s): %s", socket->permit->hostname->content, newline); reason = nterfacer_new_rline(newline, sock, &number); if(reason) { if(reason == RE_SOCKET_ERROR) return BUF_ERROR; if(reason != RE_BAD_LINE) { if(esocket_write_line(sock, "%d,E%d,%s", number, reason, request_error(reason))) return BUF_ERROR; return 0; } else { return 1; } } break; } return 0; }
Session_Manager_SQL::Session_Manager_SQL(std::shared_ptr<SQL_Database> db, const std::string& passphrase, RandomNumberGenerator& rng, size_t max_sessions, std::chrono::seconds session_lifetime) : m_db(db), m_rng(rng), m_max_sessions(max_sessions), m_session_lifetime(session_lifetime) { m_db->create_table( "create table if not exists tls_sessions " "(" "session_id TEXT PRIMARY KEY, " "session_start INTEGER, " "hostname TEXT, " "hostport INTEGER, " "session BLOB" ")"); m_db->create_table( "create table if not exists tls_sessions_metadata " "(" "passphrase_salt BLOB, " "passphrase_iterations INTEGER, " "passphrase_check INTEGER " ")"); const size_t salts = m_db->row_count("tls_sessions_metadata"); if(salts == 1) { // existing db auto stmt = m_db->new_statement("select * from tls_sessions_metadata"); if(stmt->step()) { std::pair<const byte*, size_t> salt = stmt->get_blob(0); const size_t iterations = stmt->get_size_t(1); const size_t check_val_db = stmt->get_size_t(2); size_t check_val_created; m_session_key = derive_key(passphrase, salt.first, salt.second, iterations, check_val_created); if(check_val_created != check_val_db) throw std::runtime_error("Session database password not valid"); } } else { // maybe just zap the salts + sessions tables in this case? if(salts != 0) throw std::runtime_error("Seemingly corrupted database, multiple salts found"); // new database case std::vector<byte> salt = unlock(rng.random_vec(16)); const size_t iterations = 256 * 1024; size_t check_val = 0; m_session_key = derive_key(passphrase, salt.data(), salt.size(), iterations, check_val); auto stmt = m_db->new_statement("insert into tls_sessions_metadata values(?1, ?2, ?3)"); stmt->bind(1, salt); stmt->bind(2, iterations); stmt->bind(3, check_val); stmt->spin(); } }
/************************************************* * Derive a key * *************************************************/ SecureVector<byte> DH_PrivateKey::derive_key(const byte w[], u32bit w_len) const { return derive_key(BigInt::decode(w, w_len)); }
// Verify message 1 then generate and return message 2 to isv. int sp_ra_proc_msg1_req(const sample_ra_msg1_t *p_msg1, uint32_t msg1_size, ra_samp_response_header_t **pp_msg2) { int ret = 0; ra_samp_response_header_t* p_msg2_full = NULL; sample_ra_msg2_t *p_msg2 = NULL; sample_ecc_state_handle_t ecc_state = NULL; sample_status_t sample_ret = SAMPLE_SUCCESS; bool derive_ret = false; if(!p_msg1 || !pp_msg2 || (msg1_size != sizeof(sample_ra_msg1_t))) { return -1; } // Check to see if we have registered? if (!g_is_sp_registered) { return SP_UNSUPPORTED_EXTENDED_EPID_GROUP; } do { // Get the sig_rl from attestation server using GID. // GID is Base-16 encoded of EPID GID in little-endian format. // In the product, the SP and attesation server uses an established channel for // communication. uint8_t* sig_rl; uint32_t sig_rl_size = 0; // The product interface uses a REST based message to get the SigRL. ret = g_sp_extended_epid_group_id->get_sigrl(p_msg1->gid, &sig_rl_size, &sig_rl); if(0 != ret) { fprintf(stderr, "\nError, ias_get_sigrl [%s].", __FUNCTION__); ret = SP_IAS_FAILED; break; } // Need to save the client's public ECCDH key to local storage if (memcpy_s(&g_sp_db.g_a, sizeof(g_sp_db.g_a), &p_msg1->g_a, sizeof(p_msg1->g_a))) { fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // Generate the Service providers ECCDH key pair. sample_ret = sample_ecc256_open_context(&ecc_state); if(SAMPLE_SUCCESS != sample_ret) { fprintf(stderr, "\nError, cannot get ECC context in [%s].", __FUNCTION__); ret = -1; break; } sample_ec256_public_t pub_key = {{0},{0}}; sample_ec256_private_t priv_key = {{0}}; sample_ret = sample_ecc256_create_key_pair(&priv_key, &pub_key, ecc_state); if(SAMPLE_SUCCESS != sample_ret) { fprintf(stderr, "\nError, cannot generate key pair in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // Need to save the SP ECCDH key pair to local storage. if(memcpy_s(&g_sp_db.b, sizeof(g_sp_db.b), &priv_key,sizeof(priv_key)) || memcpy_s(&g_sp_db.g_b, sizeof(g_sp_db.g_b), &pub_key,sizeof(pub_key))) { fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // Generate the client/SP shared secret sample_ec_dh_shared_t dh_key = {{0}}; sample_ret = sample_ecc256_compute_shared_dhkey(&priv_key, (sample_ec256_public_t *)&p_msg1->g_a, (sample_ec256_dh_shared_t *)&dh_key, ecc_state); if(SAMPLE_SUCCESS != sample_ret) { fprintf(stderr, "\nError, compute share key fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } #ifdef SUPPLIED_KEY_DERIVATION // smk is only needed for msg2 generation. derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK_SK, &g_sp_db.smk_key, &g_sp_db.sk_key); if(derive_ret != true) { fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // The rest of the keys are the shared secrets for future communication. derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK_VK, &g_sp_db.mk_key, &g_sp_db.vk_key); if(derive_ret != true) { fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } #else // smk is only needed for msg2 generation. derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK, &g_sp_db.smk_key); if(derive_ret != true) { fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // The rest of the keys are the shared secrets for future communication. derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK, &g_sp_db.mk_key); if(derive_ret != true) { fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SK, &g_sp_db.sk_key); if(derive_ret != true) { fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_VK, &g_sp_db.vk_key); if(derive_ret != true) { fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } #endif uint32_t msg2_size = sizeof(sample_ra_msg2_t) + sig_rl_size; p_msg2_full = (ra_samp_response_header_t*)malloc(msg2_size + sizeof(ra_samp_response_header_t)); if(!p_msg2_full) { fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } memset(p_msg2_full, 0, msg2_size + sizeof(ra_samp_response_header_t)); p_msg2_full->type = TYPE_RA_MSG2; p_msg2_full->size = msg2_size; // The simulated message2 always passes. This would need to be set // accordingly in a real service provider implementation. p_msg2_full->status[0] = 0; p_msg2_full->status[1] = 0; p_msg2 = (sample_ra_msg2_t *)p_msg2_full->body; // Assemble MSG2 if(memcpy_s(&p_msg2->g_b, sizeof(p_msg2->g_b), &g_sp_db.g_b, sizeof(g_sp_db.g_b)) || memcpy_s(&p_msg2->spid, sizeof(sample_spid_t), &g_spid, sizeof(g_spid))) { fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // The service provider is responsible for selecting the proper EPID // signature type and to understand the implications of the choice! p_msg2->quote_type = SAMPLE_QUOTE_LINKABLE_SIGNATURE; #ifdef SUPPLIED_KEY_DERIVATION //isv defined key derivation function id #define ISV_KDF_ID 2 p_msg2->kdf_id = ISV_KDF_ID; #else p_msg2->kdf_id = SAMPLE_AES_CMAC_KDF_ID; #endif // Create gb_ga sample_ec_pub_t gb_ga[2]; if(memcpy_s(&gb_ga[0], sizeof(gb_ga[0]), &g_sp_db.g_b, sizeof(g_sp_db.g_b)) || memcpy_s(&gb_ga[1], sizeof(gb_ga[1]), &g_sp_db.g_a, sizeof(g_sp_db.g_a))) { fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // Sign gb_ga sample_ret = sample_ecdsa_sign((uint8_t *)&gb_ga, sizeof(gb_ga), (sample_ec256_private_t *)&g_sp_priv_key, (sample_ec256_signature_t *)&p_msg2->sign_gb_ga, ecc_state); if(SAMPLE_SUCCESS != sample_ret) { fprintf(stderr, "\nError, sign ga_gb fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } // Generate the CMACsmk for gb||SPID||TYPE||KDF_ID||Sigsp(gb,ga) uint8_t mac[SAMPLE_EC_MAC_SIZE] = {0}; uint32_t cmac_size = offsetof(sample_ra_msg2_t, mac); sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.smk_key, (uint8_t *)&p_msg2->g_b, cmac_size, &mac); if(SAMPLE_SUCCESS != sample_ret) { fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } if(memcpy_s(&p_msg2->mac, sizeof(p_msg2->mac), mac, sizeof(mac))) { fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } if(memcpy_s(&p_msg2->sig_rl[0], sig_rl_size, sig_rl, sig_rl_size)) { fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); ret = SP_INTERNAL_ERROR; break; } p_msg2->sig_rl_size = sig_rl_size; }while(0); if(ret) { *pp_msg2 = NULL; SAFE_FREE(p_msg2_full); } else { // Freed by the network simulator in ra_free_network_response_buffer *pp_msg2 = p_msg2_full; } if(ecc_state) { sample_ecc256_close_context(ecc_state); } return ret; }
/************************************************* * Derive a key * *************************************************/ SecureVector<byte> DH_PrivateKey::derive_key(const DH_PublicKey& key) const { return derive_key(key.get_y()); }
static int populate_create_encryption_params_nvlists(libzfs_handle_t *hdl, zfs_handle_t *zhp, boolean_t newkey, zfs_keyformat_t keyformat, char *keylocation, nvlist_t *props, uint8_t **wkeydata, uint_t *wkeylen) { int ret; uint64_t iters = 0, salt = 0; uint8_t *key_material = NULL; size_t key_material_len = 0; uint8_t *key_data = NULL; const char *fsname = (zhp) ? zfs_get_name(zhp) : NULL; /* get key material from keyformat and keylocation */ ret = get_key_material(hdl, B_TRUE, newkey, keyformat, keylocation, fsname, &key_material, &key_material_len, NULL); if (ret != 0) goto error; /* passphrase formats require a salt and pbkdf2 iters property */ if (keyformat == ZFS_KEYFORMAT_PASSPHRASE) { /* always generate a new salt */ random_init(); ret = random_get_bytes((uint8_t *)&salt, sizeof (uint64_t)); if (ret != 0) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Failed to generate salt.")); goto error; } random_fini(); ret = nvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), salt); if (ret != 0) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Failed to add salt to properties.")); goto error; } /* * If not otherwise specified, use the default number of * pbkdf2 iterations. If specified, we have already checked * that the given value is greater than MIN_PBKDF2_ITERATIONS * during zfs_valid_proplist(). */ ret = nvlist_lookup_uint64(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); if (ret == ENOENT) { iters = DEFAULT_PBKDF2_ITERATIONS; ret = nvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), iters); if (ret != 0) goto error; } else if (ret != 0) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Failed to get pbkdf2 iterations.")); goto error; } } else { /* check that pbkdf2iters was not specified by the user */ ret = nvlist_lookup_uint64(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); if (ret == 0) { ret = EINVAL; zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Cannot specify pbkdf2iters with a non-passphrase " "keyformat.")); goto error; } } /* derive a key from the key material */ ret = derive_key(hdl, keyformat, iters, key_material, key_material_len, salt, &key_data); if (ret != 0) goto error; free(key_material); *wkeydata = key_data; *wkeylen = WRAPPING_KEY_LEN; return (0); error: if (key_material != NULL) free(key_material); if (key_data != NULL) free(key_data); *wkeydata = NULL; *wkeylen = 0; return (ret); }
// Saves file with specified index and closes file descriptor (if force is 1, // attempts to save data even if file is not yet complete). Returns 0 on // success and -1 on error. int Saverestoredfile(int slot,int force) { int n,success; ushort filecrc; ulong l,length; uchar *bufout,*data,*tempdata,*salt,key[AESKEYLEN],iv[16]; t_fproc *pf; aes_decrypt_ctx ctx[1]; HANDLE hfile; if (slot<0 || slot>=NFILE) return -1; // Invalid index of file descriptor pf=fproc+slot; if (pf->busy==0 || pf->nblock==0) return -1; // Index points to unused descriptor if (pf->ndata!=pf->nblock && force==0) return -1; // Still incomplete data Message("",0); // If data is encrypted, decrypt it to temporary buffer. Decryption in place // is possible, but the whole data would be lost if password is incorrect. if (pf->mode & PBM_ENCRYPTED) { if (pf->datasize & 0x0000000F) { Reporterror("Encrypted data is not aligned"); return -1; }; if (Getpassword()!=0) return -1; // User cancelled decryption tempdata=(uchar *)GlobalAlloc(GMEM_FIXED,pf->datasize); if (tempdata==NULL) { Reporterror("Low memory, can't decrypt data"); return -1; }; n=strlen(password); salt=(uchar *)(pf->name)+32; // hack: put the salt & iv at the end of the name field derive_key((const uchar *)password, n, salt, 16, 524288, key, AESKEYLEN); memset(password,0,sizeof(password)); memset(ctx,0,sizeof(aes_decrypt_ctx)); if(aes_decrypt_key((const uchar *)key,AESKEYLEN,ctx) == EXIT_FAILURE) { memset(key,0,AESKEYLEN); Reporterror("Failed to set decryption key"); return -1; }; memset(key,0,AESKEYLEN); memcpy(iv, salt+16, 16); // the second 16-byte block in 'salt' is the IV if(aes_cbc_decrypt(pf->data,tempdata,pf->datasize,iv,ctx) == EXIT_FAILURE) { Reporterror("Failed to decrypt data"); memset(ctx,0,sizeof(aes_decrypt_ctx)); return -1; }; memset(ctx,0,sizeof(aes_decrypt_ctx)); filecrc=Crc16(tempdata,pf->datasize); if (filecrc!=(ushort)pf->filecrc) { Reporterror("Invalid password, please try again"); GlobalFree((HGLOBAL)tempdata); return -1; } else { GlobalFree((HGLOBAL)pf->data); pf->data=tempdata; pf->mode&=~PBM_ENCRYPTED; }; }; // If data is compressed, unpack it to temporary buffer. if ((pf->mode & PBM_COMPRESSED)==0) { // Data is not compressed. data=pf->data; length=pf->origsize; bufout=NULL; } else { // Data is compressed. Create temporary buffer. if (pf->origsize==0) pf->origsize=pf->datasize*4; // Weak attempt to recover bufout=(uchar *)GlobalAlloc(GMEM_FIXED,pf->origsize); if (bufout==NULL) { Reporterror("Low memory"); return -1; }; // Unpack data. length=pf->origsize; success=BZ2_bzBuffToBuffDecompress((char *)bufout,(uint *)&length, (char *)pf->data,pf->datasize,0,0); if (success!=BZ_OK) { GlobalFree((HGLOBAL)bufout); Reporterror("Unable to unpack data"); return -1; }; data=bufout; }; // Ask user for file name. if (Selectoutfile(pf->name)!=0) { // Cancelled by user if (bufout!=NULL) GlobalFree((HGLOBAL)bufout); return -1; }; // Open file and save data. hfile=CreateFile(outfile,GENERIC_WRITE,0,NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if (hfile==INVALID_HANDLE_VALUE) { if (bufout!=NULL) GlobalFree((HGLOBAL)bufout); Reporterror("Unable to create file"); return -1; }; WriteFile(hfile,data,length,&l,NULL); // Restore old modification date and time. SetFileTime(hfile,&pf->modified,&pf->modified,&pf->modified); // Close file and restore old basic attributes. CloseHandle(hfile); SetFileAttributes(outfile,pf->attributes); if (bufout!=NULL) GlobalFree((HGLOBAL)bufout); if (l!=length) { Reporterror("I/O error"); return -1; }; // Close file descriptor and report success. Closefproc(slot); Message("File saved",0); return 0; };
/* * Save all files in rootdir to a container */ int memfile_savefiles(char * filename, char * password, memfile * root) { FILE * f ; int i ; uint8_t nonce[NONCE_SZ]; uint8_t key[KEY_SZ]; uint8_t canari[CANARI_SZ]; char enc_name[MAXNAMESZ]; uint64_t u1, u2, u3 ; size_t offset=0 ; /* Generate nonce */ memcpy(nonce, get_nonce(), NONCE_SZ); /* Derive key from password */ derive_key(password, strlen(password), nonce, NONCE_SZ, key, KEY_SZ, 20000); /* * A container header is composed of: * A magic number of MAGIC_SZ bytes * A version number on 2 bytes: major.minor * A nonce of size NONCE_SZ bytes * A canari of size CANARI_SZ bytes */ if ((f=fopen(filename, "w"))==NULL) { return 0 ; } /* Write magic number */ fwrite(mefs_magic, 1, MAGIC_SZ, f); /* Write version */ fwrite(mefs_version, 1, 2, f); /* Write nonce */ fwrite(nonce, 1, NONCE_SZ, f); /* Generate and encrypt canari */ for (i=0 ; i<CANARI_SZ ; i++) { canari[i] = 0xaa ; } stream_cipher(canari, CANARI_SZ, 0, key, nonce); fwrite(canari, 1, CANARI_SZ, f); offset += CANARI_SZ ; /* Write files one by one */ /* * filename is a zero-padded string of size MAXNAMESZ * filesize on a 64 big-endian unsigned int * ctime on a 64-big-endian unsigned int * mtime on a 64-big-endian unsigned int */ for (i=0 ; i<MAXFILES ; i++) { if (root[i].name==NULL) { continue ; } memset(enc_name, 0, MAXNAMESZ); strncpy(enc_name, root[i].name, MAXNAMESZ); stream_cipher(enc_name, MAXNAMESZ, offset, key, nonce); offset += MAXNAMESZ ; fwrite(enc_name, 1, MAXNAMESZ, f); u1 = root[i].sta.st_size ; u2 = root[i].sta.st_ctime ; u3 = root[i].sta.st_mtime ; stream_cipher((uint8_t*)&u1, sizeof(uint64_t), offset, key, nonce); offset += sizeof(uint64_t); fwrite(&u1, sizeof(uint64_t), 1, f); stream_cipher((uint8_t*)&u2, sizeof(uint64_t), offset, key, nonce); offset += sizeof(uint64_t); fwrite(&u2, sizeof(uint64_t), 1, f); stream_cipher((uint8_t*)&u3, sizeof(uint64_t), offset, key, nonce); offset += sizeof(uint64_t); fwrite(&u3, sizeof(uint64_t), 1, f); stream_cipher(root[i].data, root[i].sta.st_size, offset, key, nonce); offset += root[i].sta.st_size ; fwrite(root[i].data, 1, root[i].sta.st_size, f); } fclose(f); return 0 ; }
/* * Read a container with the provided key * Read all files and place them into the provided list * Returns: * >0 Number of read files * -1 File error during reading * -2 Wrong password in input */ int memfile_readfiles(char * filename, char * password, memfile * root) { char * buf ; char * cur ; int fd ; int i ; struct stat fileinfo ; uint8_t nonce[NONCE_SZ]; uint8_t key[KEY_SZ]; uint64_t u1, u2, u3 ; size_t header_sz ; size_t payload_sz ; char fname[MAXNAMESZ]; header_sz = MAGIC_SZ + 2 + NONCE_SZ + CANARI_SZ ; /* Find out file size in bytes */ if (stat(filename, &fileinfo)!=0) { logger("no such file: %s", filename); return 1 ; } if (fileinfo.st_size < header_sz) { logger("not a container: ", filename); return -1 ; } /* Map input file */ if ((fd=open(filename, O_RDONLY))==-1) { logger("cannot open: %s", filename); return -1 ; } buf = (char*)mmap(0, fileinfo.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (buf==(char*)-1) { logger("cannot map: %s", filename); return -1; } cur = buf ; payload_sz = fileinfo.st_size - header_sz ; /* * A container header is composed of: * A magic number of MAGIC_SZ bytes * A version number on 2 bytes: major.minor * A nonce of size NONCE_SZ bytes * A canari of size CANARI_SZ bytes */ /* Check magic number */ for (i=0 ; i<MAGIC_SZ ; i++) { if (cur[i]!=mefs_magic[i]) { logger("not a container: ", filename); munmap(buf, fileinfo.st_size); return -1 ; } } cur += MAGIC_SZ ; /* Read version number */ if (cur[0]!=mefs_version[0] || cur[1]!=mefs_version[1]) { logger("unsupported version for: ", filename); munmap(buf, fileinfo.st_size); return -1 ; } cur+=2 ; /* Copy nonce for later use */ memcpy(nonce, cur, NONCE_SZ); cur += NONCE_SZ ; /* Derive key from password */ derive_key(password, strlen(password), nonce, NONCE_SZ, key, KEY_SZ, 20000); /* Decrypt everything starting from CANARI, using nonce and key */ stream_cipher(cur, fileinfo.st_size-(MAGIC_SZ+2+NONCE_SZ), 0, key, nonce); /* Test canari has expected pattern: 0xaaaa...aa */ for (i=0 ; i<CANARI_SZ ; i++) { if ((unsigned char)cur[i]!=0xaa) { logger("wrong password for container: %s", filename); munmap(buf, fileinfo.st_size); return -2 ; } } cur+=CANARI_SZ ; /* Read files one by one */ /* * filename is a zero-padded string of size MAXNAMESZ * filesize on a 64 big-endian unsigned int * ctime on a 64-big-endian unsigned int * mtime on a 64-big-endian unsigned int */ i=0 ; while (1) { memcpy(fname, cur, MAXNAMESZ); cur+=MAXNAMESZ; memcpy(&u1, cur, sizeof(uint64_t)); cur+=sizeof(uint64_t); memcpy(&u2, cur, sizeof(uint64_t)); cur+=sizeof(uint64_t); memcpy(&u3, cur, sizeof(uint64_t)); cur+=sizeof(uint64_t); root[i].name = strdup(fname); root[i].sta.st_ino = inode_next(); root[i].sta.st_size = u1 ; root[i].sta.st_ctime = u2 ; root[i].sta.st_mtime = u3 ; root[i].data = malloc(u1); memcpy(root[i].data, cur, u1); cur+=u1 ; if ((cur-buf) >= fileinfo.st_size) break ; i++ ; } munmap(buf, fileinfo.st_size); return 0 ; }
extern "C" sgx_status_t sgx_ra_proc_msg2_trusted( sgx_ra_context_t context, const sgx_ra_msg2_t *p_msg2, //(g_b||spid||quote_type|| KDF_ID ||sign_gb_ga||cmac||sig_rl_size||sig_rl) const sgx_target_info_t *p_qe_target, sgx_report_t *p_report, sgx_quote_nonce_t* p_nonce) { sgx_status_t se_ret = SGX_ERROR_UNEXPECTED; //p_msg2[in] p_qe_target[in] p_report[out] p_nonce[out] in EDL file if(vector_size(&g_ra_db) <= context || !p_msg2 || !p_qe_target || !p_report || !p_nonce) return SGX_ERROR_INVALID_PARAMETER; ra_db_item_t* item = NULL; if(0 != vector_get(&g_ra_db, context, reinterpret_cast<void**>(&item)) || item == NULL ) return SGX_ERROR_INVALID_PARAMETER; sgx_ec256_private_t a; memset(&a, 0, sizeof(a)); // Create gb_ga sgx_ec256_public_t gb_ga[2]; sgx_ec256_public_t sp_pubkey; sgx_ec_key_128bit_t smkey = {0}; sgx_ec_key_128bit_t skey = {0}; sgx_ec_key_128bit_t mkey = {0}; sgx_ec_key_128bit_t vkey = {0}; sgx_ra_derive_secret_keys_t ra_key_cb = NULL; memset(&gb_ga[0], 0, sizeof(gb_ga)); sgx_spin_lock(&item->item_lock); //sgx_ra_get_ga must have been called if (item->state != ra_get_gaed) { sgx_spin_unlock(&item->item_lock); return SGX_ERROR_INVALID_STATE; } memcpy(&a, &item->a, sizeof(a)); memcpy(&gb_ga[1], &item->g_a, sizeof(gb_ga[1])); memcpy(&sp_pubkey, &item->sp_pubkey, sizeof(sp_pubkey)); ra_key_cb = DEC_KDF_POINTER(item->derive_key_cb); sgx_spin_unlock(&item->item_lock); memcpy(&gb_ga[0], &p_msg2->g_b, sizeof(gb_ga[0])); sgx_ecc_state_handle_t ecc_state = NULL; // ecc_state need to be freed when exit. se_ret = sgx_ecc256_open_context(&ecc_state); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; return se_ret; } sgx_ec256_dh_shared_t dh_key; memset(&dh_key, 0, sizeof(dh_key)); sgx_ec256_public_t* p_msg2_g_b = const_cast<sgx_ec256_public_t*>(&p_msg2->g_b); se_ret = sgx_ecc256_compute_shared_dhkey(&a, (sgx_ec256_public_t*)p_msg2_g_b, &dh_key, ecc_state); if(SGX_SUCCESS != se_ret) { if (SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_ecc256_close_context(ecc_state); return se_ret; } // Verify signature of gb_ga uint8_t result; sgx_ec256_signature_t* p_msg2_sign_gb_ga = const_cast<sgx_ec256_signature_t*>(&p_msg2->sign_gb_ga); se_ret = sgx_ecdsa_verify((uint8_t *)&gb_ga, sizeof(gb_ga), &sp_pubkey, p_msg2_sign_gb_ga, &result, ecc_state); if(SGX_SUCCESS != se_ret) { if (SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_ecc256_close_context(ecc_state); return se_ret; } if(SGX_EC_VALID != result) { sgx_ecc256_close_context(ecc_state); return SGX_ERROR_INVALID_SIGNATURE; } do { if(NULL != ra_key_cb) { se_ret = ra_key_cb(&dh_key, p_msg2->kdf_id, &smkey, &skey, &mkey, &vkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret && SGX_ERROR_INVALID_PARAMETER != se_ret && SGX_ERROR_KDF_MISMATCH != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } } else if (p_msg2->kdf_id == 0x0001) { se_ret = derive_key(&dh_key, "SMK", (uint32_t)(sizeof("SMK") -1), &smkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } se_ret = derive_key(&dh_key, "SK", (uint32_t)(sizeof("SK") -1), &skey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } se_ret = derive_key(&dh_key, "MK", (uint32_t)(sizeof("MK") -1), &mkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } se_ret = derive_key(&dh_key, "VK", (uint32_t)(sizeof("VK") -1), &vkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } } else { se_ret = SGX_ERROR_KDF_MISMATCH; break; } sgx_cmac_128bit_tag_t mac; uint32_t maced_size = offsetof(sgx_ra_msg2_t, mac); se_ret = sgx_rijndael128_cmac_msg(&smkey, (const uint8_t *)p_msg2, maced_size, &mac); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } //Check mac if(0 == consttime_memequal(mac, p_msg2->mac, sizeof(mac))) { se_ret = SGX_ERROR_MAC_MISMATCH; break; } //create a nonce se_ret =sgx_read_rand((uint8_t*)p_nonce, sizeof(sgx_quote_nonce_t)); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } sgx_spin_lock(&item->item_lock); //sgx_ra_get_ga must have been called if (item->state != ra_get_gaed) { se_ret = SGX_ERROR_INVALID_STATE; sgx_spin_unlock(&item->item_lock); break; } memcpy(&item->g_b, &p_msg2->g_b, sizeof(item->g_b)); memcpy(&item->smk_key, smkey, sizeof(item->smk_key)); memcpy(&item->sk_key, skey, sizeof(item->sk_key)); memcpy(&item->mk_key, mkey, sizeof(item->mk_key)); memcpy(&item->vk_key, vkey, sizeof(item->vk_key)); memcpy(&item->qe_target, p_qe_target, sizeof(sgx_target_info_t)); memcpy(&item->quote_nonce, p_nonce, sizeof(sgx_quote_nonce_t)); sgx_report_data_t report_data = {{0}}; se_static_assert(sizeof(sgx_report_data_t)>=sizeof(sgx_sha256_hash_t)); // H = SHA256(ga || gb || VK_CMAC) uint32_t sha256ed_size = offsetof(ra_db_item_t, sp_pubkey); //report_data is 512bits, H is 256bits. The H is in the lower 256 bits of report data while the higher 256 bits are all zeros. se_ret = sgx_sha256_msg((uint8_t *)&item->g_a, sha256ed_size, (sgx_sha256_hash_t *)&report_data); if(SGX_SUCCESS != se_ret) { if (SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_spin_unlock(&item->item_lock); break; } //REPORTDATA = H se_ret = sgx_create_report(p_qe_target, &report_data, p_report); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_spin_unlock(&item->item_lock); break; } item->state = ra_proc_msg2ed; sgx_spin_unlock(&item->item_lock); }while(0); memset_s(&dh_key, sizeof(dh_key), 0, sizeof(dh_key)); sgx_ecc256_close_context(ecc_state); memset_s(&a, sizeof(sgx_ec256_private_t),0, sizeof(sgx_ec256_private_t)); memset_s(smkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); memset_s(skey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); memset_s(mkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); memset_s(vkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); return se_ret; }
int main (int argc, char **argv) { const char *ke_msg1 = NULL; char *ke_msg2 = NULL; char *ca_file = NULL; char *sk_file = NULL; char *cert_file = NULL; char *resp_id = NULL; int out_fd; flow1 *to_b = NULL; flow2 *from_b = NULL; cert *own_cert = NULL; dckey *sk = NULL; dckey *ca_pk = NULL; u_char seskey[sha1_hashsize], secret[aes_blocklen]; char *pretty_secret = NULL; if ((argc == 5) && argv[1][0] != '-') { /* no -p option */ ca_file = "./.pki/ca.pub"; } else if ((argc == 6) && (argv[1][0] != '-') && (argv[1] + 1) && (argv[1][1] != 'p') && (argv[1] + 2)) { /* -p option present, followed by CERT-FILE without separating blank */ ca_file = argv[1] + 2; } else if ((argc == 7) && !strcmp (argv[1], "-p")) { /* -p option present, followed by blank and CERT-FILE */ ca_file = argv[2]; } else { usage (argv[0]); /* does not return */ } setprogname (argv[0]); ri (); sk_file = argv[argc - 4]; cert_file = argv[argc - 3]; resp_id = argv[argc - 2]; out_fd = atoi (argv[argc - 1]); if (!cert_verify (own_cert = cert_read (cert_file))) { fprintf (stderr, "%s: trouble reading certificate from %s, or certificate expired\n", getprogname (), cert_file); perror (getprogname ()); exit (1); } else { to_b = prepare_ke_msg (own_cert, xstrdup (resp_id)); sk = sk_from_file (sk_file); ke_msg1 = export_ke_msg (to_b, sk); dcfree (sk); sk = NULL; write_chunk (1, ke_msg1, strlen (ke_msg1)); check_n_free ((char **) &ke_msg1); ca_pk = pk_from_file (ca_file); if (!(ke_msg2 = read_line (0)) || !(from_b = process_ke_reply (to_b, ke_msg2, ca_pk))) { fprintf (stderr, "error reading/parsing bob's message:\n%s", ke_msg2); dcfree (ca_pk); ca_pk = NULL; check_n_free(&ke_msg2); exit (1); } dcfree (ca_pk); ca_pk = NULL; check_n_free(&ke_msg2); /* derive_key looks at seskey to know if it the caller is alice or bob */ seskey[0] = 'a'; if (derive_key (seskey, to_b, from_b) == -1) { fprintf (stderr, "error deriving session key for alice.\n"); flow1_clr (to_b); flow2_clr (from_b); exit (1); } else { /* choose a random number to send */ prng_getbytes (secret, aes_blocklen); cat_buf (&pretty_secret, secret, aes_blocklen); /* send it to bob, encrypted under the newly established session key */ send_secret (1, secret, seskey); /* dump the chosen secret to standard error */ if ((write_chunk (out_fd, pretty_secret, strlen (pretty_secret)) == -1) || (write_chunk (out_fd, "\n", 1) == -1)) { fprintf (stderr, "error writing to the launcher.\n"); bzero (seskey, sha1_hashsize); bzero (secret, sizeof (secret)); bzero (pretty_secret, strlen (pretty_secret)); xfree (pretty_secret); pretty_secret = NULL; flow1_clr (to_b); flow2_clr (from_b); exit (1); } /* wipe out sensitive data */ bzero (seskey, sha1_hashsize); bzero (secret, sizeof (secret)); bzero (pretty_secret, strlen (pretty_secret)); xfree (pretty_secret); pretty_secret = NULL; flow1_clr (to_b); flow2_clr (from_b); } } /* fprintf (stderr, "alice:done.\n"); */ return 0; }