Пример #1
0
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());
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}