Connection::Connection(CryptoIdentity& ci, Path path, ConnectionPool& cp, ConnectionHandler& ch) : Forwarding(randint64()) , _ci(&ci) , _cp(cp) , _ch(ch) , _naclsession( std::get<1>(path.at(path.size()-1))->enc_key() ) , _their_id( std::get<1>(path.at(path.size()-1))->id() ) , _route_id( bytes( id() ) ) , _authenticated(false) , _request_packet(new std::string) , _packet_queue(new std::vector<std::string>) , _nonces(nullptr) { _request_packet->push_back('\1'); std::string nonce = _route_id + randomstring(8); _request_packet->append(nonce); nonce.resize(crypto_box_NONCEBYTES,'\0'); RoutingRequest rq; rq.set_enc_algo(enumval(PkencAlgo::CURVE25519XSALSA20POLY1305)); rq.set_sender_pubkey(_naclsession.our_pk()); Hop hop; { hop.set_type(Hop::UP); hop.set_nonce_algo(Hop::XTEA32); rq.set_details(_naclsession.encrypt(hop.SerializeAsString(), nonce)); } hop.Clear(); hop.set_type(Hop::SIMPLE); hop.set_next(_their_id); for (signed int i=path.size()-2; i>=0; --i) { auto dev = std::get<1>(path[i]); hop.set_details(rq.details()); rq.set_details( crypto_box( hop.SerializeAsString(), nonce, dev->enc_key(), _naclsession.our_sk()) ); hop.set_next(dev->id()); } rq.AppendToString(_request_packet.get()); }
int enc_map(Encoder* enc, ERL_NIF_TERM head, ERL_NIF_TERM tail) { int arity; const ERL_NIF_TERM* tuple; if(yajl_gen_map_open(enc->handle) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "failed_to_open_map"); return ERROR; } do { if(!enif_get_tuple(enc->env, head, &arity, &tuple)) { enc->error = enif_make_tuple(enc->env, 2, enif_make_atom(enc->env, "badarg"), head ); return ERROR; } if(arity != 2) { enc->error = enif_make_tuple(enc->env, 2, enif_make_atom(enc->env, "badarity"), head ); return ERROR; } if(enc_key(enc, tuple[0]) != OK) return ERROR; if(enc_json(enc, tuple[1]) != OK) return ERROR; } while(enif_get_list_cell(enc->env, tail, &head, &tail)); if(yajl_gen_map_close(enc->handle) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "failed_to_close_map"); return ERROR; } return OK; }
krb5_error_code krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage, const krb5_data *kd_data, krb5_crypto_iov *data, size_t num_data) { const struct krb5_enc_provider *enc = &krb5int_enc_arcfour; const struct krb5_hash_provider *hash = &krb5int_hash_md5; krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; krb5_error_code ret; ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, &usage_keyblock); if (ret != 0) goto cleanup; ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, &enc_keyblock); if (ret != 0) goto cleanup; /* Derive a usage key from the session key and usage. */ ret = usage_key(enc, hash, keyblock, usage, usage_keyblock); if (ret != 0) goto cleanup; /* Derive the encryption key from the usage key and kd_data. */ ret = enc_key(enc, hash, usage_keyblock, kd_data, enc_keyblock); if (ret != 0) goto cleanup; /* Encrypt or decrypt (encrypt_iov works for both) the input. */ ret = keyblock_crypt(enc, enc_keyblock, 0, data, num_data); cleanup: krb5int_c_free_keyblock(NULL, usage_keyblock); krb5int_c_free_keyblock(NULL, enc_keyblock); return ret; }
krb5_error_code krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp, krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) { const struct krb5_enc_provider *enc = ktp->enc; const struct krb5_hash_provider *hash = ktp->hash; krb5_error_code ret; krb5_crypto_iov *header, *trailer; krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; krb5_data checksum, header_data, comp_checksum = empty_data(); header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); if (header == NULL || header->data.length != hash->hashsize + CONFOUNDERLENGTH) return KRB5_BAD_MSIZE; header_data = header->data; trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); if (trailer != NULL && trailer->data.length != 0) return KRB5_BAD_MSIZE; /* Allocate buffers. */ ret = alloc_data(&comp_checksum, hash->hashsize); if (ret != 0) goto cleanup; ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, &usage_keyblock); if (ret != 0) goto cleanup; ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, &enc_keyblock); if (ret != 0) goto cleanup; checksum = make_data(header->data.data, hash->hashsize); /* Adjust pointers so confounder is at start of header. */ header->data.length -= hash->hashsize; header->data.data += hash->hashsize; /* We may have to try two usage values; see below. */ do { /* Derive a usage key from the session key and usage. */ ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock); if (ret != 0) goto cleanup; /* Derive the encryption key from the usage key and checksum. */ ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock); if (ret) goto cleanup; /* Decrypt the ciphertext. */ ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data); if (ret != 0) goto cleanup; /* Compute HMAC(usage key, plaintext) to get the checksum. */ ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data, &comp_checksum); if (ret != 0) goto cleanup; if (k5_bcmp(checksum.data, comp_checksum.data, hash->hashsize) != 0) { if (usage == 9) { /* * RFC 4757 specifies usage 8 for TGS-REP encrypted parts * encrypted in a subkey, but the value used by MS is actually * 9. We now use 9 to start with, but fall back to 8 on * failure in case we are communicating with a KDC using the * value from the RFC. ivec is always NULL in this case. * We need to re-encrypt the data in the wrong key first. */ ret = keyblock_crypt(enc, enc_keyblock, NULL, data, num_data); if (ret != 0) goto cleanup; usage = 8; continue; } ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; goto cleanup; } break; } while (1); cleanup: header->data = header_data; /* Restore header pointers. */ krb5int_c_free_keyblock(NULL, usage_keyblock); krb5int_c_free_keyblock(NULL, enc_keyblock); zapfree(comp_checksum.data, comp_checksum.length); return ret; }
krb5_error_code krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp, krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) { const struct krb5_enc_provider *enc = ktp->enc; const struct krb5_hash_provider *hash = ktp->hash; krb5_error_code ret; krb5_crypto_iov *header, *trailer; krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; krb5_data checksum, confounder, header_data; size_t i; /* * Caller must have provided space for the header, padding * and trailer; per RFC 4757 we will arrange it as: * * Checksum | E(Confounder | Plaintext) */ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); if (header == NULL || header->data.length < hash->hashsize + CONFOUNDERLENGTH) return KRB5_BAD_MSIZE; header_data = header->data; /* Trailer may be absent. */ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); if (trailer != NULL) trailer->data.length = 0; /* Ensure that there is no padding. */ for (i = 0; i < num_data; i++) { if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING) data[i].data.length = 0; } ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, &usage_keyblock); if (ret != 0) goto cleanup; ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, &enc_keyblock); if (ret != 0) goto cleanup; /* Derive a usage key from the session key and usage. */ ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock); if (ret != 0) goto cleanup; /* Generate a confounder in the header block, after the checksum. */ header->data.length = hash->hashsize + CONFOUNDERLENGTH; confounder = make_data(header->data.data + hash->hashsize, CONFOUNDERLENGTH); ret = krb5_c_random_make_octets(0, &confounder); if (ret != 0) goto cleanup; checksum = make_data(header->data.data, hash->hashsize); /* Adjust pointers so confounder is at start of header. */ header->data.length -= hash->hashsize; header->data.data += hash->hashsize; /* Compute the checksum using the usage key. */ ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data, &checksum); if (ret != 0) goto cleanup; /* Derive the encryption key from the usage key and checksum. */ ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock); if (ret) goto cleanup; ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data); cleanup: header->data = header_data; /* Restore header pointers. */ krb5int_c_free_keyblock(NULL, usage_keyblock); krb5int_c_free_keyblock(NULL, enc_keyblock); return ret; }