Exemple #1
0
struct secret *hsm_do_ecdh(const tal_t *ctx, const struct pubkey *point)
{
	struct secret *ss = tal(ctx, struct secret);
	if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey,
			   notsosecret.data, NULL, NULL) != 1)
		return tal_free(ss);
	return ss;
}
Exemple #2
0
static void bench_ecdh(void* arg) {
    int i;
    unsigned char res[32];
    bench_ecdh_t *data = (bench_ecdh_t*)arg;

    for (i = 0; i < 20000; i++) {
        CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1);
    }
}
SECP256K1_API jobjectArray JNICALL Java_org_commercium_NativeSecp256k1_secp256k1_1ecdh
  (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen)
{
  secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
  const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject);
  const unsigned char* pubdata = (const unsigned char*) (secdata + 32);

  jobjectArray retArray;
  jbyteArray outArray, intsByteArray;
  unsigned char intsarray[1];
  secp256k1_pubkey pubkey;
  unsigned char nonce_res[32];
  size_t outputLen = 32;

  int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen);

  if (ret) {
    ret = secp256k1_ecdh(
      ctx,
      nonce_res,
      &pubkey,
      secdata
    );
  }

  intsarray[0] = ret;

  retArray = (*env)->NewObjectArray(env, 2,
    (*env)->FindClass(env, "[B"),
    (*env)->NewByteArray(env, 1));

  outArray = (*env)->NewByteArray(env, outputLen);
  (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res);
  (*env)->SetObjectArrayElement(env, retArray, 0, outArray);

  intsByteArray = (*env)->NewByteArray(env, 1);
  (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray);
  (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);

  (void)classObject;

  return retArray;
}
/*
 * Decrypt onion, return true if onion->hop[0] is valid.
 *
 * Returns enckey and pad_iv for use in unwrap.
 */
static bool decrypt_onion(const struct seckey *myseckey, struct onion *onion,
			  struct enckey *enckey, struct iv *pad_iv)
{
	secp256k1_context *ctx;
	unsigned char secret[32];
	struct hmackey hmackey;
	struct iv iv;
	secp256k1_pubkey pubkey;

	ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);

	if (!pubkey_parse(ctx, &pubkey, &myhop(onion)->pubkey))
		goto fail;
	
	/* Extract shared secret. */
	if (!secp256k1_ecdh(ctx, secret, &pubkey, myseckey->u.u8))
		goto fail;

	hmackey = hmackey_from_secret(secret);
	*enckey = enckey_from_secret(secret);
	ivs_from_secret(secret, &iv, pad_iv);

	/* Check HMAC. */
#if 0
	printf("Checking HMAC using key%02x%02x%02x%02x%02x%02x%02x%02x (offset %u len %zu) for %02x%02x%02x%02x%02x%02x%02x%02x...%02x%02x%02x\n",
	       hmackey.k[0], hmackey.k[1],
	       hmackey.k[2], hmackey.k[3],
	       hmackey.k[4], hmackey.k[5],
	       hmackey.k[6], hmackey.k[7],
	       SHA256_DIGEST_LENGTH,
	       sizeof(*onion) - SHA256_DIGEST_LENGTH,
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[0],
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[1],
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[2],
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[3],
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[4],
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[5],
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[6],
	       ((unsigned char *)onion + SHA256_DIGEST_LENGTH)[7],
	       ((unsigned char *)(onion + 1))[-3],
	       ((unsigned char *)(onion + 1))[-2],
	       ((unsigned char *)(onion + 1))[-1]);
	dump_contents((unsigned char *)onion + SHA256_DIGEST_LENGTH,
		      sizeof(*onion) - SHA256_DIGEST_LENGTH);
#endif
	if (!check_hmac(onion, &hmackey))
		goto fail;

	/* Decrypt everything up to pubkey. */
	/* FIXME: Assumes we can decrypt in place! */
	if (!aes_decrypt(onion, onion,
			 sizeof(struct hop) * (MAX_HOPS-1)
			 + sizeof(myhop(onion)->msg),
			 enckey, &iv))
		goto fail;
	
	secp256k1_context_destroy(ctx);
	return true;

fail:
	secp256k1_context_destroy(ctx);
	return false;
}
static bool create_onion(const secp256k1_pubkey pubkey[],
			 char *const msg[],
			 size_t num,
			 struct onion *onion)
{
	int i;
	struct seckey seckeys[MAX_HOPS];
	struct onion_pubkey pubkeys[MAX_HOPS];
	struct enckey enckeys[MAX_HOPS];
	struct hmackey hmackeys[MAX_HOPS];
	struct iv ivs[MAX_HOPS];
	struct iv pad_ivs[MAX_HOPS];
	HMAC_CTX padding_hmac[MAX_HOPS];
	struct hop padding[MAX_HOPS];
	size_t junk_hops;
	secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
	bool ok = false;

	if (num > MAX_HOPS)
		goto fail;

	/* FIXME: I think it would be safe to reuse a single disposable key
	 * here? */
	/* First generate all the keys. */
	for (i = 0; i < num; i++) {
		unsigned char secret[32];

		gen_keys(ctx, &seckeys[i], &pubkeys[i]);


		/* Make shared secret. */
		if (!secp256k1_ecdh(ctx, secret, &pubkey[i], seckeys[i].u.u8))
			goto fail;

		hmackeys[i] = hmackey_from_secret(memcheck(secret, 32));
		enckeys[i] = enckey_from_secret(secret);
		ivs_from_secret(secret, &ivs[i], &pad_ivs[i]);
	}

	/*
	 * Building the onion is a little tricky.
	 *
	 * First, there is the padding.  That's generated by previous nodes,
	 * and "decrypted" by the others.  So we have to generate that
	 * forwards.
	 */
	for (i = 0; i < num; i++) {
		if (i > 0) {
			/* Previous node decrypts padding before passing on. */
			aes_decrypt(padding, padding, sizeof(struct hop)*(i-1),
				    &enckeys[i-1], &ivs[i-1]);
			memmove(padding + 1, padding,
				sizeof(struct hop)*(i-1));
		}
		/* And generates more padding for next node. */
		add_padding(&padding[0], &enckeys[i-1], &pad_ivs[i-1]);
		HMAC_CTX_init(&padding_hmac[i]);
		HMAC_Init_ex(&padding_hmac[i],
			     hmackeys[i].k.u.u8, sizeof(hmackeys[i].k),
			     EVP_sha256(), NULL);
		HMAC_Update(&padding_hmac[i],
			    memcheck((unsigned char *)padding,
				     i * sizeof(struct hop)),
			    i * sizeof(struct hop));
	}

	/*
	 * Now the normal onion is generated backwards.
	 */

	/* Unused hops filled with random, so even recipient can't tell
	 * how many were used. */
	junk_hops = MAX_HOPS - num;
	random_bytes(onion->hop, junk_hops * sizeof(struct hop));

	for (i = num - 1; i >= 0; i--) {
		size_t other_hops, len;
		struct hop *myhop;

		other_hops = num - i - 1 + junk_hops;

		/* Our entry is at tail of onion. */
		myhop = onion->hop + other_hops;

		/* Now populate our hop. */
		myhop->pubkey = pubkeys[i];
		/* Set message. */
		assert(strlen(msg[i]) < MESSAGE_SIZE);
		memset(myhop->msg, 0, MESSAGE_SIZE);
		strcpy((char *)myhop->msg, msg[i]);

		/* Encrypt whole thing, including our message, but we
		 * aware it will be offset by the prepended padding. */
		if (!aes_encrypt_offset(i * sizeof(struct hop),
					onion, onion,
					other_hops * sizeof(struct hop)
					+ sizeof(myhop->msg),
					&enckeys[i], &ivs[i]))
			goto fail;

		/* HMAC covers entire thing except hmac itself. */
		len = (other_hops + 1)*sizeof(struct hop) - sizeof(myhop->hmac);
		HMAC_Update(&padding_hmac[i],
			    memcheck((unsigned char *)onion, len), len);
		HMAC_Final(&padding_hmac[i], myhop->hmac.u.u8, NULL);
	}

	ok = true;
fail:
	secp256k1_context_destroy(ctx);
	return ok;
}