示例#1
0
文件: sshecc.c 项目: gdh1995/putty
static mp_int *ecdsa_signing_exponent_from_data(
    const struct ec_curve *curve, const struct ecsign_extra *extra,
    ptrlen data)
{
    /* Hash the data being signed. */
    unsigned char hash[MAX_HASH_LEN];
    ssh_hash *h = ssh_hash_new(extra->hash);
    put_datapl(h, data);
    ssh_hash_final(h, hash);

    /*
     * Take the leftmost b bits of the hash of the signed data (where
     * b is the number of bits in order(G)), interpreted big-endian.
     */
    mp_int *z = mp_from_bytes_be(make_ptrlen(hash, extra->hash->hlen));
    size_t zbits = mp_get_nbits(z);
    size_t nbits = mp_get_nbits(curve->w.G_order);
    size_t shift = zbits - nbits;
    /* Bound the shift count below at 0, using bit twiddling to avoid
     * a conditional branch */
    shift &= ~-(shift >> (CHAR_BIT * sizeof(size_t) - 1));
    mp_int *toret = mp_rshift_safe(z, shift);
    mp_free(z);

    return toret;
}
示例#2
0
static void oaep_mask(const ssh_hashalg *h, void *seed, int seedlen,
		      void *vdata, int datalen)
{
    unsigned char *data = (unsigned char *)vdata;
    unsigned count = 0;

    while (datalen > 0) {
        int i, max = (datalen > h->hlen ? h->hlen : datalen);
        ssh_hash *s;
        unsigned char hash[MAX_HASH_LEN];

	assert(h->hlen <= MAX_HASH_LEN);
        s = ssh_hash_new(h);
        put_data(s, seed, seedlen);
        put_uint32(s, count);
        ssh_hash_final(s, hash);
        count++;

        for (i = 0; i < max; i++)
            data[i] ^= hash[i];

        data += max;
        datalen -= max;
    }
}
示例#3
0
/*
 * Generate a fingerprint string for the key. Compatible with the
 * OpenSSH fingerprint code.
 */
char *rsa_ssh1_fingerprint(RSAKey *key)
{
    unsigned char digest[16];
    strbuf *out;
    int i;

    /*
     * The hash preimage for SSH-1 key fingerprinting consists of the
     * modulus and exponent _without_ any preceding length field -
     * just the minimum number of bytes to represent each integer,
     * stored big-endian, concatenated with no marker at the division
     * between them.
     */

    ssh_hash *hash = ssh_hash_new(&ssh_md5);
    for (size_t i = (mp_get_nbits(key->modulus) + 7) / 8; i-- > 0 ;)
        put_byte(hash, mp_get_byte(key->modulus, i));
    for (size_t i = (mp_get_nbits(key->exponent) + 7) / 8; i-- > 0 ;)
        put_byte(hash, mp_get_byte(key->exponent, i));
    ssh_hash_final(hash, digest);

    out = strbuf_new();
    strbuf_catf(out, "%d ", mp_get_nbits(key->modulus));
    for (i = 0; i < 16; i++)
	strbuf_catf(out, "%s%02x", i ? ":" : "", digest[i]);
    if (key->comment)
        strbuf_catf(out, " %s", key->comment);
    return strbuf_to_str(out);
}
示例#4
0
Boolean
ssh_tls_ssl_prf(const unsigned char *secret, int secret_len,
                const unsigned char *random_1, int random_1_len,
                const unsigned char *random_2, int random_2_len,
                unsigned char *return_buf, int return_len)
{
  unsigned char label;
  int i, j;
  SshHash md5, sha1;
  unsigned char sha_digest[20];

  SSH_ASSERT(return_len % 16 == 0);
  SSH_ASSERT(return_len < 400);
  
  if (ssh_hash_allocate("md5", &md5) != SSH_CRYPTO_OK) 
    return FALSE;
  if (ssh_hash_allocate("sha1", &sha1) != SSH_CRYPTO_OK)
    return FALSE;
  
  for (i = 1, label = 'A';
       return_len > 0;
       i++, label++, return_buf += 16, return_len -= 16)
    {
      ssh_hash_reset(sha1);
      
      for (j = 0; j < i; j++)
        ssh_hash_update(sha1, &label, 1);
      
      ssh_hash_update(sha1, secret, secret_len);
      ssh_hash_update(sha1, random_1, random_1_len);
      ssh_hash_update(sha1, random_2, random_2_len);
      if (ssh_hash_final(sha1, sha_digest) != SSH_CRYPTO_OK) 
	return FALSE;
      
      ssh_hash_reset(md5);
      
      ssh_hash_update(md5, secret, secret_len);
      ssh_hash_update(md5, sha_digest, 20);
      if (ssh_hash_final(md5, return_buf) != SSH_CRYPTO_OK) 
	return FALSE;
    }
  
  ssh_hash_free(md5); ssh_hash_free(sha1);
  return TRUE;
}
示例#5
0
SshCryptoStatus
ssh_hash_of_buffer(const char *type,
                   const void *buf, size_t len,
                   unsigned char *digest)
{
  SshHash hash;
  SshCryptoStatus status;

  if ((status = ssh_hash_allocate(type, &hash)) != SSH_CRYPTO_OK)
    return status;

  ssh_hash_update(hash, buf, len);
  status = ssh_hash_final(hash, digest);
  ssh_hash_free(hash);

  return status;
}
示例#6
0
文件: sshecc.c 项目: gdh1995/putty
static mp_int *eddsa_signing_exponent_from_data(
    struct eddsa_key *ek, const struct ecsign_extra *extra,
    ptrlen r_encoded, ptrlen data)
{
    /* Hash (r || public key || message) */
    unsigned char hash[MAX_HASH_LEN];
    ssh_hash *h = ssh_hash_new(extra->hash);
    put_datapl(h, r_encoded);
    put_epoint(h, ek->publicKey, ek->curve, true); /* omit string header */
    put_datapl(h, data);
    ssh_hash_final(h, hash);

    /* Convert to an integer */
    mp_int *toret = mp_from_bytes_le(make_ptrlen(hash, extra->hash->hlen));

    smemclr(hash, extra->hash->hlen);
    return toret;
}
示例#7
0
void
ssh_pm_ike_id_hash(SshPm pm, unsigned char hash[SSH_ENGINE_PEER_ID_SIZE],
                   SshIkev2PayloadID id)
{
  unsigned char digest[SSH_MAX_HASH_DIGEST_LENGTH];

  ssh_hash_reset(pm->hash);
  ssh_hash_update(pm->hash, (unsigned char *) &id->id_type,
		  sizeof(id->id_type));
  ssh_hash_update(pm->hash, id->id_data, id->id_data_size);

  memset(digest, 0, SSH_MAX_HASH_DIGEST_LENGTH);
  if (ssh_hash_final(pm->hash, digest) != SSH_CRYPTO_OK)
    SSH_DEBUG(SSH_D_ERROR, ("Hash failed"));

  /* Use the first bytes of the digest as the hash value. */
  SSH_ASSERT(SSH_ENGINE_PEER_ID_SIZE <= SSH_MAX_HASH_DIGEST_LENGTH);
  memcpy(hash, digest, SSH_ENGINE_PEER_ID_SIZE);
}
示例#8
0
void bcrypt_genblock(int counter,
                     const unsigned char hashed_passphrase[64],
                     const unsigned char *salt, int saltbytes,
                     unsigned char output[32])
{
    unsigned char hashed_salt[64];

    /* Hash the input salt with the counter value optionally suffixed
     * to get our real 32-byte salt */
    ssh_hash *h = ssh_hash_new(&ssh_sha512);
    put_data(h, salt, saltbytes);
    if (counter)
        put_uint32(h, counter);
    ssh_hash_final(h, hashed_salt);

    bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output);

    smemclr(&hashed_salt, sizeof(hashed_salt));
}
示例#9
0
int
main(int argc, char *argv[])
{
  SshHash hash;
  unsigned char buf[16];
  int i, j;

  if (ssh_crypto_library_initialize() != SSH_CRYPTO_OK)
    ssh_fatal("Could not initialize the crypto library.");

  if (ssh_hash_allocate("md5", &hash) != SSH_CRYPTO_OK)
    {
      fprintf(stderr, "could not allocate MD5 hash\n");
      exit(1);
    }

  for (i = 1; i < argc; i++)
    {
      ssh_hash_reset(hash);

      ssh_hash_update(hash, argv[i], strlen(argv[i]));
      if (ssh_hash_final(hash, buf) != SSH_CRYPTO_OK)
        {
          fprintf(stderr, "could not compute MD5 hash digest\n");
          exit(1);
        }

      printf("\
  {\"%s\",\n\
   \"",
             argv[i]);

      for (j = 0; j < sizeof(buf); j++)
        printf("\\x%02x", buf[j]);

      printf("\", %d , %d,\n\
   0, 0, 0, 0},\n", sizeof(buf), sizeof(buf));
    }

  return 0;
}
示例#10
0
文件: sshecc.c 项目: gdh1995/putty
EdwardsPoint *eddsa_public(mp_int *private_key, const ssh_keyalg *alg)
{
    const struct ecsign_extra *extra =
        (const struct ecsign_extra *)alg->extra;
    struct ec_curve *curve = extra->curve();
    assert(curve->type == EC_EDWARDS);

    ssh_hash *h = ssh_hash_new(extra->hash);
    for (size_t i = 0; i < curve->fieldBytes; ++i)
        put_byte(h, mp_get_byte(private_key, i));

    unsigned char hash[MAX_HASH_LEN];
    ssh_hash_final(h, hash);

    mp_int *exponent = eddsa_exponent_from_hash(
        make_ptrlen(hash, extra->hash->hlen), curve);

    EdwardsPoint *toret = ecc_edwards_multiply(curve->e.G, exponent);
    mp_free(exponent);

    return toret;
}
示例#11
0
static unsigned char *rsa_pkcs1_signature_string(
    size_t nbytes, const ssh_hashalg *halg, ptrlen data)
{
    size_t fixed_parts = rsa_pkcs1_length_of_fixed_parts(halg);
    assert(nbytes >= fixed_parts);
    size_t padding = nbytes - fixed_parts;

    ptrlen asn1_prefix = rsa_pkcs1_prefix_for_hash(halg);

    unsigned char *bytes = snewn(nbytes, unsigned char);

    bytes[0] = 0;
    bytes[1] = 1;

    memset(bytes + 2, 0xFF, padding);

    memcpy(bytes + 2 + padding, asn1_prefix.ptr, asn1_prefix.len);

    ssh_hash *h = ssh_hash_new(halg);
    put_datapl(h, data);
    ssh_hash_final(h, bytes + 2 + padding + asn1_prefix.len);

    return bytes;
}
示例#12
0
文件: sshecc.c 项目: gdh1995/putty
static void eddsa_sign(ssh_key *key, ptrlen data,
                       unsigned flags, BinarySink *bs)
{
    struct eddsa_key *ek = container_of(key, struct eddsa_key, sshk);
    const struct ecsign_extra *extra =
        (const struct ecsign_extra *)ek->sshk.vt->extra;
    assert(ek->privateKey);

    /*
     * EdDSA prescribes a specific method of generating the random
     * nonce integer for the signature. (A verifier can't tell
     * whether you followed that method, but it's important to
     * follow it anyway, because test vectors will want a specific
     * signature for a given message, and because this preserves
     * determinism of signatures even if the same signature were
     * made twice by different software.)
     */

    /*
     * First, we hash the private key integer (bare, little-endian)
     * into a hash generating 2*fieldBytes of output.
     */
    unsigned char hash[MAX_HASH_LEN];
    ssh_hash *h = ssh_hash_new(extra->hash);
    for (size_t i = 0; i < ek->curve->fieldBytes; ++i)
        put_byte(h, mp_get_byte(ek->privateKey, i));
    ssh_hash_final(h, hash);

    /*
     * The first half of the output hash is converted into an
     * integer a, by the standard EdDSA transformation.
     */
    mp_int *a = eddsa_exponent_from_hash(
        make_ptrlen(hash, ek->curve->fieldBytes), ek->curve);

    /*
     * The second half of the hash of the private key is hashed again
     * with the message to be signed, and used as an exponent to
     * generate the signature point r.
     */
    h = ssh_hash_new(extra->hash);
    put_data(h, hash + ek->curve->fieldBytes,
             extra->hash->hlen - ek->curve->fieldBytes);
    put_datapl(h, data);
    ssh_hash_final(h, hash);
    mp_int *log_r_unreduced = mp_from_bytes_le(
        make_ptrlen(hash, extra->hash->hlen));
    mp_int *log_r = mp_mod(log_r_unreduced, ek->curve->e.G_order);
    mp_free(log_r_unreduced);
    EdwardsPoint *r = ecc_edwards_multiply(ek->curve->e.G, log_r);

    /*
     * Encode r now, because we'll need its encoding for the next
     * hashing step as well as to write into the actual signature.
     */
    strbuf *r_enc = strbuf_new();
    put_epoint(r_enc, r, ek->curve, true); /* omit string header */
    ecc_edwards_point_free(r);

    /*
     * Compute the hash of (r || public key || message) just as
     * eddsa_verify does.
     */
    mp_int *H = eddsa_signing_exponent_from_data(
        ek, extra, ptrlen_from_strbuf(r_enc), data);

    /* And then s = (log(r) + H*a) mod order(G). */
    mp_int *Ha = mp_modmul(H, a, ek->curve->e.G_order);
    mp_int *s = mp_modadd(log_r, Ha, ek->curve->e.G_order);
    mp_free(H);
    mp_free(a);
    mp_free(Ha);
    mp_free(log_r);

    /* Format the output */
    put_stringz(bs, ek->sshk.vt->ssh_id);
    put_uint32(bs, r_enc->len + ek->curve->fieldBytes);
    put_data(bs, r_enc->u, r_enc->len);
    strbuf_free(r_enc);
    for (size_t i = 0; i < ek->curve->fieldBytes; ++i)
        put_byte(bs, mp_get_byte(s, i));
    mp_free(s);
}
示例#13
0
SshCryptoStatus
ssh_rsa_oaep_encode_with_mgf1(const char *hash_name,
			      const unsigned char *msg,
			      size_t msg_len,
			      const unsigned char *param,
			      size_t param_len,
			      unsigned char *emsg, size_t emsg_len)
{
  unsigned char *db;
  unsigned char seed[SSH_MAX_HASH_DIGEST_LENGTH];
  size_t db_len, i, digest_len;
  SshHash hash;
  SshCryptoStatus status;

  if ((status = ssh_hash_allocate(hash_name, &hash)) != SSH_CRYPTO_OK)
    return status;

  digest_len = ssh_hash_digest_length(hash_name);

  /* Check that the size constraints are satisfied. */
  if (msg_len > emsg_len - 2 * digest_len - 1)
    {
      ssh_hash_free(hash);
      return SSH_CRYPTO_OPERATION_FAILED;
    }

  /* This is: emLen - ||M|| - 2hLen - 1  + hLen + 1 + ||M|| =
     emLen - hLen. */
  db_len = emsg_len - digest_len;
  if ((db = ssh_calloc(1, db_len)) == NULL)
    {
      ssh_hash_free(hash);
      return SSH_CRYPTO_NO_MEMORY;
    }

  ssh_hash_update(hash, param, param_len);
  if ((status = ssh_hash_final(hash, db)) != SSH_CRYPTO_OK)
    {
      ssh_hash_free(hash);
      return status;
    }

  /* Add the "01" before the last msg_len bytes. */
  db[db_len - msg_len - 1] = 0x1;

  /* Now throw in the msg. */
  memcpy(db + db_len - msg_len, msg, msg_len);

  /* Generate a random octet string. */
  for (i = 0; i < digest_len; i++)
    seed[i] = ssh_random_get_byte();

  /* Now use the MGF1. */
  if ((status = ssh_rsa_mgf1(hash_name,
			     seed, digest_len,
			     emsg + digest_len, db_len))
      != SSH_CRYPTO_OK)
    {
      ssh_hash_free(hash);
      ssh_free(db);
      return status;
    }

  /* Xor. */
  for (i = 0; i < db_len; i++)
    emsg[digest_len + i] ^= db[i];
  memset(db, 0, db_len);

  /* Use MGF1 again. */
  if ((status = ssh_rsa_mgf1(hash_name,
			     emsg + digest_len, db_len,
			     emsg, digest_len))
      != SSH_CRYPTO_OK)
    {
      ssh_hash_free(hash);
      ssh_free(db);
      return status;
    }

  /* Xor the seed. */
  for (i = 0; i < digest_len; i++)
    emsg[i] ^= seed[i];
  memset(seed, 0, digest_len);

  /* Now free the allocated information. */
  ssh_hash_free(hash);
  ssh_free(db);

  return SSH_CRYPTO_OK;
}
示例#14
0
/* OAEP decode using MGF1. */
SshCryptoStatus
ssh_rsa_oaep_decode_with_mgf1(const char *hash_name,
			      const unsigned char *emsg,
			      size_t emsg_len,
			      const unsigned char *param,
			      size_t param_len,
			      unsigned char **msg, size_t *msg_len)
{
  unsigned char  seed[SSH_MAX_HASH_DIGEST_LENGTH];
  unsigned char  phash[SSH_MAX_HASH_DIGEST_LENGTH];
  unsigned char *db = NULL;
  size_t         db_len, i, digest_len;
  SshHash hash;
  SshCryptoStatus status;

  if ((status = ssh_hash_allocate(hash_name, &hash)) != SSH_CRYPTO_OK)
    return status;

  digest_len = ssh_hash_digest_length(hash_name);

  if (emsg_len < 2 * digest_len + 1)
    {
      status = SSH_CRYPTO_OPERATION_FAILED;
      goto failed;
    }

  /* Allocate enough working buffers. */
  db_len = emsg_len - digest_len;
  if ((db = ssh_malloc(db_len)) == NULL)
    {
      status = SSH_CRYPTO_NO_MEMORY;
      goto failed;
    }

  /* Use the mgf. */
  if ((status = ssh_rsa_mgf1(hash_name, emsg + digest_len, db_len,
			     seed, digest_len))
      != SSH_CRYPTO_OK)
    {
      goto failed;
    }

  /* Now xor. */
  for (i = 0; i < digest_len; i++)
    seed[i] ^= emsg[i];

  /* Use the mgf again. */
  if ((status = ssh_rsa_mgf1(hash_name, seed, digest_len, db, db_len))
      != SSH_CRYPTO_OK)
    {
      goto failed;
    }

  /* Now xor again. */
  for (i = 0; i < db_len; i++)
    db[i] ^= emsg[digest_len + i];

  ssh_hash_update(hash, param, param_len);
  if ((status = ssh_hash_final(hash, phash)) != SSH_CRYPTO_OK)
    {
      goto failed;
    }

  /* Do the check. */
  if (memcmp(db, phash, digest_len) != 0)
    {
      status = SSH_CRYPTO_OPERATION_FAILED;
      goto failed;
    }

  for (i = digest_len; i < db_len; i++)
    {
      if (db[i] != 0)
        {
          if (db[i] != 0x1)
	    {
	      status = SSH_CRYPTO_OPERATION_FAILED;
	      goto failed;
	    }
          break;
        }
    }
  if (i >= db_len)
    {
      status = SSH_CRYPTO_OPERATION_FAILED;
      goto failed;
    }

  /* Now we must have db[i] == 0x1. */
  *msg_len = db_len - i - 1;
  if ((*msg = ssh_malloc(*msg_len)) == NULL)
    {
      status = SSH_CRYPTO_NO_MEMORY;
      goto failed;
    }
  memcpy(*msg, db + i + 1, *msg_len);
  status = SSH_CRYPTO_OK;

failed:
  ssh_hash_free(hash);
  ssh_free(db);

  return status;
}
示例#15
0
static void
ssh_eap_md5_client_recv_token(SshEapProtocol protocol,
                              SshEap eap,
                              SshBuffer buf)
{
  SshEapMd5State state;
  SshEapMd5Params params;
  SshBuffer pkt = NULL;
  SshUInt8 b;
  SshHash hash = NULL;
  SshCryptoStatus status;
  unsigned long len;
  unsigned long name_len;
  unsigned long secret_len;
  SshUInt8 *secret_ptr;
  SshEapToken t;
  SshUInt8 hashbuf[32];

  if (ssh_eap_get_token_type_from_buf(buf) != SSH_EAP_TOKEN_SHARED_SECRET)
    {
      ssh_eap_discard_token(eap, protocol, buf, ("unexpected token type"));
      return;
    }

  t = (SshEapToken)ssh_buffer_ptr(buf);
  if (t == NULL)
    {
      ssh_eap_discard_token(eap, protocol, buf, ("invalid token"));
      return;
    }

  secret_ptr = ssh_eap_get_token_secret_ptr(t);
  secret_len = ssh_eap_get_token_secret_len(t);

  SSH_ASSERT(secret_ptr != NULL || secret_len == 0);

  state = ssh_eap_protocol_get_state(protocol);
  params = ssh_eap_protocol_get_params(protocol);

  status = SSH_CRYPTO_UNSUPPORTED;
  name_len = 0;

  if (params != NULL && params->name_buffer != NULL)
    {
      name_len = params->name_length;
    }

  if (state->challenge_buffer == NULL)
    {
      ssh_eap_discard_token(eap, protocol, buf,
                            "EAP MD5 state lacks authenticator challenge");
      goto fail_auth;
    }

  status = ssh_hash_allocate("md5", &hash);

  if (status != SSH_CRYPTO_OK)
    {
      ssh_eap_discard_token(eap, protocol, buf,
                            "failed to initialize MD5 function");
      goto fail_auth;
    }

  len = ssh_hash_digest_length(ssh_hash_name(hash));

  if (len > 32)
    {
      ssh_eap_fatal(eap, protocol,
                    "MD5 output of unexpected size");
      goto fail_auth;
    }

  pkt = ssh_eap_create_reply(eap,
                             (SshUInt16)(1 + len + name_len),
                             protocol->impl->id);

  if (pkt == NULL)
    {
      ssh_eap_fatal(eap, protocol,
                    "Out of memory. Could not allocate reply packet.");
      goto fail_auth;
    }

  b = (SshUInt8)(len & 0xFF);

  if (ssh_buffer_append(pkt,&b,1) != SSH_BUFFER_OK)
    {
      ssh_eap_fatal(eap, protocol,
                    "Out of memory. Could not build reply packet.");
      goto fail_auth;
    }

  ssh_hash_reset(hash);
  ssh_hash_update(hash, &state->response_id, 1);
  ssh_hash_update(hash, secret_ptr, secret_len);
  ssh_hash_update(hash, state->challenge_buffer, state->challenge_length);
  ssh_hash_final(hash, hashbuf);

  if (ssh_buffer_append(pkt, hashbuf, len) != SSH_BUFFER_OK)
    {
      ssh_eap_fatal(eap, protocol,
                    "Out of memory. Could not build reply packet.");
      goto fail_auth;
    }

  if (name_len > 0)
    {
      if (ssh_buffer_append(pkt, params->name_buffer, name_len)
          != SSH_BUFFER_OK)
        {
          ssh_eap_fatal(eap, protocol,
                        "Out of memory. Could not build reply packet.");
          goto fail_auth;
        }
    }

  ssh_eap_protocol_send_response(protocol, eap, pkt);
  pkt = NULL;

  ssh_eap_protocol_auth_ok(protocol, eap, SSH_EAP_SIGNAL_NONE, NULL);

 fail_auth:
  if (pkt != NULL)
    ssh_buffer_free(pkt);
  if (hash != NULL)
    ssh_hash_free(hash);

  ssh_eap_md5_reset(protocol,eap);
}
示例#16
0
strbuf *ssh_rsakex_encrypt(RSAKey *rsa, const ssh_hashalg *h, ptrlen in)
{
    mp_int *b1, *b2;
    int k, i;
    char *p;
    const int HLEN = h->hlen;

    /*
     * Here we encrypt using RSAES-OAEP. Essentially this means:
     * 
     *  - we have a SHA-based `mask generation function' which
     *    creates a pseudo-random stream of mask data
     *    deterministically from an input chunk of data.
     * 
     *  - we have a random chunk of data called a seed.
     * 
     *  - we use the seed to generate a mask which we XOR with our
     *    plaintext.
     * 
     *  - then we use _the masked plaintext_ to generate a mask
     *    which we XOR with the seed.
     * 
     *  - then we concatenate the masked seed and the masked
     *    plaintext, and RSA-encrypt that lot.
     * 
     * The result is that the data input to the encryption function
     * is random-looking and (hopefully) contains no exploitable
     * structure such as PKCS1-v1_5 does.
     * 
     * For a precise specification, see RFC 3447, section 7.1.1.
     * Some of the variable names below are derived from that, so
     * it'd probably help to read it anyway.
     */

    /* k denotes the length in octets of the RSA modulus. */
    k = (7 + mp_get_nbits(rsa->modulus)) / 8;

    /* The length of the input data must be at most k - 2hLen - 2. */
    assert(in.len > 0 && in.len <= k - 2*HLEN - 2);

    /* The length of the output data wants to be precisely k. */
    strbuf *toret = strbuf_new_nm();
    int outlen = k;
    unsigned char *out = strbuf_append(toret, outlen);

    /*
     * Now perform EME-OAEP encoding. First set up all the unmasked
     * output data.
     */
    /* Leading byte zero. */
    out[0] = 0;
    /* At position 1, the seed: HLEN bytes of random data. */
    random_read(out + 1, HLEN);
    /* At position 1+HLEN, the data block DB, consisting of: */
    /* The hash of the label (we only support an empty label here) */
    {
        ssh_hash *s = ssh_hash_new(h);
        ssh_hash_final(s, out + HLEN + 1);
    }
    /* A bunch of zero octets */
    memset(out + 2*HLEN + 1, 0, outlen - (2*HLEN + 1));
    /* A single 1 octet, followed by the input message data. */
    out[outlen - in.len - 1] = 1;
    memcpy(out + outlen - in.len, in.ptr, in.len);

    /*
     * Now use the seed data to mask the block DB.
     */
    oaep_mask(h, out+1, HLEN, out+HLEN+1, outlen-HLEN-1);

    /*
     * And now use the masked DB to mask the seed itself.
     */
    oaep_mask(h, out+HLEN+1, outlen-HLEN-1, out+1, HLEN);

    /*
     * Now `out' contains precisely the data we want to
     * RSA-encrypt.
     */
    b1 = mp_from_bytes_be(make_ptrlen(out, outlen));
    b2 = mp_modpow(b1, rsa->exponent, rsa->modulus);
    p = (char *)out;
    for (i = outlen; i--;) {
	*p++ = mp_get_byte(b2, i);
    }
    mp_free(b1);
    mp_free(b2);

    /*
     * And we're done.
     */
    return toret;
}
示例#17
0
SshCMStatus ssh_cm_add_crl_with_bindings(SshCMCrl crl,
                                         SshCertDBKey *bindings)
{
  SshCertDBEntry *entry;
  SshCMContext cm = crl->cm;

  SSH_DEBUG(5, ("CRL add to local database/memory cache."));

  if (crl == NULL || cm->db == NULL)
    {
      ssh_certdb_key_free(bindings);
      return SSH_CM_STATUS_FAILURE;
    }

  if (cm->config->local_db_writable == FALSE)
    {
      ssh_certdb_key_free(bindings);
      return SSH_CM_STATUS_FAILURE;
    }

  /* Allocate a new entry. */
  if (ssh_certdb_alloc_entry(cm->db,
                             SSH_CM_DATA_TYPE_CRL, crl,
                             &entry) != SSH_CDBET_OK)
    {
      ssh_certdb_key_free(bindings);
      return SSH_CM_STATUS_COULD_NOT_ALLOCATE;
    }

  SSH_DEBUG(SSH_D_MIDOK, ("Explicit crl: %@", ssh_cm_render_crl, crl->crl));

  /* Check for collision in the database. Be a optimist anyway... */
  if (ssh_cm_crl_check_db_collision(cm, crl, &entry->names))
    {
      unsigned char digest[SSH_MAX_HASH_DIGEST_LENGTH];
      size_t length;
      SshHash hash;
      SshCertDBEntryList *found;
      SshCertDBEntryListNode list;
      SshCMCrl old_crl;

      /* First fetch colliding old CRL from local cache, timestamp it and
         clean possible SSH_CM_CRL_FLAG_SKIP-flag */
      if (ssh_hash_allocate(SSH_CM_HASH_ALGORITHM, &hash) != SSH_CRYPTO_OK)
        {
          SSH_DEBUG(SSH_D_ERROR, ("Can't allocate %s", 
                                  SSH_CM_HASH_ALGORITHM));
          
          ssh_certdb_release_entry(cm->db, entry);
          ssh_certdb_key_free(bindings);
          
          return SSH_CM_STATUS_COULD_NOT_ALLOCATE;
        }
      
      ssh_hash_update(hash, crl->ber, crl->ber_length);
      ssh_hash_final(hash, digest);
      length = ssh_hash_digest_length(ssh_hash_name(hash));
      ssh_hash_free(hash);
  
      if (length > 8)
        length = 8;
      
      /* Get old CRL from the database. */
      if ((ssh_certdb_find(cm->db,
                           SSH_CM_DATA_TYPE_CRL,
                           SSH_CM_KEY_TYPE_BER_HASH,
                           digest, length,
                           &found) == SSH_CDBET_OK) &&
          found->head)
        {                                                    
          list = found->head;
          
          old_crl = list->entry->context;
          
          ssh_ber_time_set_from_unix_time(&old_crl->fetch_time,
                                          (*cm->config->time_func)
                                          (cm->config->time_context));
      
          old_crl->status_flags &= ~SSH_CM_CRL_FLAG_SKIP;

          SSH_DEBUG(SSH_D_MIDOK, ("CRL exists already in the database, "
                                  "updated CRL fetch-time."));
        }
      else
        {
          SSH_DEBUG(SSH_D_FAIL, ("CRL exists already in the database, "
                                 "could not update CRL fetch-time."));
        }
      
      ssh_certdb_entry_list_free_all(cm->db, found);
      
      /* Prevent database from freeing the CRL */
      entry->context = NULL;

      /* Free the entry allocated. */
      ssh_certdb_release_entry(cm->db, entry);
      ssh_certdb_key_free(bindings);

      return SSH_CM_STATUS_ALREADY_EXISTS;
    }

  /* Initialize the entry. */
  crl->entry = entry;
  if (!ssh_cm_key_set_from_crl(&entry->names, crl))
    {
      /* Prevent database from freeing the CRL */
      entry->context = NULL;
      ssh_certdb_release_entry(cm->db, entry);
      ssh_certdb_key_free(bindings);
      return SSH_CM_STATUS_COULD_NOT_ALLOCATE;
    }

  if (bindings)
    ssh_certdb_entry_add_keys(cm->db, entry, bindings);

  /* Add to the database. */
  if (ssh_certdb_add(cm->db, entry) != SSH_CDBET_OK)
    {
      /* Prevent database from freeing the CRL */
      entry->context = NULL;
      ssh_certdb_release_entry(cm->db, entry);

      SSH_DEBUG(4, ("Local database/memory cache denies the addition."));
      return SSH_CM_STATUS_COULD_NOT_ALLOCATE;
    }

  /* Record CRL addition time */
  ssh_ber_time_set_from_unix_time(&crl->fetch_time,
                                  (*cm->config->time_func)
                                  (cm->config->time_context));

  ssh_certdb_release_entry(cm->db, entry);

  return SSH_CM_STATUS_OK;
}
示例#18
0
/* There must be room for 36 bytes in `buf'. */
static Boolean generic_ssl_digest(unsigned char *secret,
				  int secret_len,
				  unsigned char *handshake_messages,
				  int handshake_messages_len,
				  Boolean is_client,
				  unsigned char *buf,
				  Boolean include_sender_token)
{
  SshHash md5, sha1;
  int i;
  
  const unsigned char client_label[4] = { 0x43, 0x4c, 0x4e, 0x54 };
  const unsigned char sender_label[4] = { 0x53, 0x52, 0x56, 0x52 };
  
  unsigned char pad_36[48], pad_5c[48];
  
  for (i = 0; i < 48; i++)
    {
      pad_36[i] = 0x36; pad_5c[i] = 0x5c;
    }
  
  SSH_ASSERT(secret_len == 48);
  
  if (ssh_hash_allocate("md5", &md5) != SSH_CRYPTO_OK)
    return FALSE;
  if (ssh_hash_allocate("sha1", &sha1) != SSH_CRYPTO_OK)
    return FALSE;
  
  ssh_hash_reset(md5);
  ssh_hash_update(md5, handshake_messages, handshake_messages_len);
  
  if (include_sender_token)
    ssh_hash_update(md5, is_client ? client_label : sender_label, 4);
  
  ssh_hash_update(md5, secret, secret_len);
  ssh_hash_update(md5, pad_36, 48);
  if (ssh_hash_final(md5, buf) != SSH_CRYPTO_OK) 
    return FALSE;
  
  ssh_hash_reset(md5);
  ssh_hash_update(md5, secret, secret_len);
  ssh_hash_update(md5, pad_5c, 48);
  ssh_hash_update(md5, buf, 16);
  if (ssh_hash_final(md5, buf) != SSH_CRYPTO_OK) 
    return FALSE;
  
  ssh_hash_reset(sha1);
  ssh_hash_update(sha1, handshake_messages, handshake_messages_len);
  
  if (include_sender_token)
    ssh_hash_update(sha1, is_client ? client_label : sender_label, 4);
  
  ssh_hash_update(sha1, secret, secret_len);
  ssh_hash_update(sha1, pad_36, 40);
  if (ssh_hash_final(sha1, buf + 16) != SSH_CRYPTO_OK) 
    return FALSE;
  
  ssh_hash_reset(sha1);
  ssh_hash_update(sha1, secret, secret_len);
  ssh_hash_update(sha1, pad_5c, 40);
  ssh_hash_update(sha1, buf + 16, 20);
  if (ssh_hash_final(sha1, buf + 16) != SSH_CRYPTO_OK) 
    return FALSE;
  
  ssh_hash_free(md5);
  ssh_hash_free(sha1);
  return TRUE;
}
示例#19
0
mp_int *ssh_rsakex_decrypt(
    RSAKey *rsa, const ssh_hashalg *h, ptrlen ciphertext)
{
    mp_int *b1, *b2;
    int outlen, i;
    unsigned char *out;
    unsigned char labelhash[64];
    ssh_hash *hash;
    BinarySource src[1];
    const int HLEN = h->hlen;

    /*
     * Decryption side of the RSA key exchange operation.
     */

    /* The length of the encrypted data should be exactly the length
     * in octets of the RSA modulus.. */
    outlen = (7 + mp_get_nbits(rsa->modulus)) / 8;
    if (ciphertext.len != outlen)
        return NULL;

    /* Do the RSA decryption, and extract the result into a byte array. */
    b1 = mp_from_bytes_be(ciphertext);
    b2 = rsa_privkey_op(b1, rsa);
    out = snewn(outlen, unsigned char);
    for (i = 0; i < outlen; i++)
        out[i] = mp_get_byte(b2, outlen-1-i);
    mp_free(b1);
    mp_free(b2);

    /* Do the OAEP masking operations, in the reverse order from encryption */
    oaep_mask(h, out+HLEN+1, outlen-HLEN-1, out+1, HLEN);
    oaep_mask(h, out+1, HLEN, out+HLEN+1, outlen-HLEN-1);

    /* Check the leading byte is zero. */
    if (out[0] != 0) {
        sfree(out);
        return NULL;
    }
    /* Check the label hash at position 1+HLEN */
    assert(HLEN <= lenof(labelhash));
    hash = ssh_hash_new(h);
    ssh_hash_final(hash, labelhash);
    if (memcmp(out + HLEN + 1, labelhash, HLEN)) {
        sfree(out);
        return NULL;
    }
    /* Expect zero bytes followed by a 1 byte */
    for (i = 1 + 2 * HLEN; i < outlen; i++) {
        if (out[i] == 1) {
            i++;  /* skip over the 1 byte */
            break;
        } else if (out[i] != 1) {
            sfree(out);
            return NULL;
        }
    }
    /* And what's left is the input message data, which should be
     * encoded as an ordinary SSH-2 mpint. */
    BinarySource_BARE_INIT(src, out + i, outlen - i);
    b1 = get_mp_ssh2(src);
    sfree(out);
    if (get_err(src) || get_avail(src) != 0) {
        mp_free(b1);
        return NULL;
    }

    /* Success! */
    return b1;
}