Example #1
0
int silc_pkcs1_import_private_key(unsigned char *key,
				  SilcUInt32 key_len,
				  void **ret_private_key)
{
  SilcAsn1 asn1;
  SilcBufferStruct alg_key;
  RsaPrivateKey *privkey;
  SilcUInt32 ver;

  if (!ret_private_key)
    return 0;

  asn1 = silc_asn1_alloc();
  if (!asn1)
    return 0;

  /* Allocate RSA private key */
  *ret_private_key = privkey = silc_calloc(1, sizeof(*privkey));
  if (!privkey)
    goto err;

  /* Parse the PKCS #1 private key */
  silc_buffer_set(&alg_key, key, key_len);
  if (!silc_asn1_decode(asn1, &alg_key,
			SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_SHORT_INT(&ver),
			  SILC_ASN1_INT(&privkey->n),
			  SILC_ASN1_INT(&privkey->e),
			  SILC_ASN1_INT(&privkey->d),
			  SILC_ASN1_INT(&privkey->p),
			  SILC_ASN1_INT(&privkey->q),
			  SILC_ASN1_INT(&privkey->dP),
			  SILC_ASN1_INT(&privkey->dQ),
			  SILC_ASN1_INT(&privkey->qP),
			SILC_ASN1_END, SILC_ASN1_END))
    goto err;

  if (ver != 0)
    goto err;

  /* Set key length */
  privkey->bits = ((silc_mp_sizeinbase(&privkey->n, 2) + 7) / 8) * 8;

  silc_asn1_free(asn1);

  return key_len;

 err:
  silc_free(privkey);
  silc_asn1_free(asn1);
  return 0;
}
Example #2
0
int silc_pkcs1_import_public_key(unsigned char *key,
				 SilcUInt32 key_len,
				 void **ret_public_key)
{
  SilcAsn1 asn1 = NULL;
  SilcBufferStruct alg_key;
  RsaPublicKey *pubkey;

  if (!ret_public_key)
    return 0;

  asn1 = silc_asn1_alloc();
  if (!asn1)
    return 0;

  /* Allocate RSA public key */
  *ret_public_key = pubkey = silc_calloc(1, sizeof(*pubkey));
  if (!pubkey)
    goto err;

  /* Parse the PKCS #1 public key */
  silc_buffer_set(&alg_key, key, key_len);
  if (!silc_asn1_decode(asn1, &alg_key,
			SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_INT(&pubkey->n),
			  SILC_ASN1_INT(&pubkey->e),
			SILC_ASN1_END, SILC_ASN1_END))
    goto err;

  /* Set key length */
  pubkey->bits = ((silc_mp_sizeinbase(&pubkey->n, 2) + 7) / 8) * 8;

  silc_asn1_free(asn1);

  return key_len;

 err:
  silc_free(pubkey);
  silc_asn1_free(asn1);
  return 0;
}
Example #3
0
static void silc_pkcs_ssh_sign_cb(SilcBool success,
				  const unsigned char *signature,
				  SilcUInt32 signature_len,
				  void *context)
{
  SilcSshSign sign = context;
  SilcStack stack = sign->stack;
  unsigned char rbuf[20], sbuf[20];
  SilcBufferStruct sig;
  SilcAsn1 asn1;
  SilcMPInt r, s;

  memset(&sig, 0, sizeof(sig));

  /* Format the signature.  RSA is easy because PKCS#1 is already in
     correct format.  For DSA the returned signature is in PKIX compliant
     format and we have to reformat it for SSH2. */
  if (!strcmp(sign->privkey->pkcs->name, "dsa")) {
    asn1 = silc_asn1_alloc(stack);
    if (!asn1) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }

    /* Decode the signature */
    silc_buffer_set(&sig, (unsigned char *)signature, signature_len);
    if (!silc_asn1_decode(asn1, &sig,
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_INT(&r),
			    SILC_ASN1_INT(&s),
			  SILC_ASN1_END, SILC_ASN1_END)) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_asn1_free(asn1);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }

    /* Encode the integers */
    memset(rbuf, 0, sizeof(rbuf));
    memset(sbuf, 0, sizeof(sbuf));
    silc_mp_mp2bin_noalloc(&r, rbuf, sizeof(rbuf));
    silc_mp_mp2bin_noalloc(&s, sbuf, sizeof(sbuf));

    silc_asn1_free(asn1);

    /* Encode SSH2 DSS signature */
    if (silc_buffer_sformat(stack, &sig,
			    SILC_STR_UI_INT(7),
			    SILC_STR_UI32_STRING("ssh-dss"),
			    SILC_STR_UI_INT(sizeof(rbuf) + sizeof(sbuf)),
			    SILC_STR_DATA(rbuf, sizeof(rbuf)),
			    SILC_STR_DATA(sbuf, sizeof(sbuf)),
			    SILC_STR_END) < 0) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }
  } else {
    /* Encode SSH2 RSA signature */
    if (silc_buffer_sformat(stack, &sig,
			    SILC_STR_UI_INT(7),
			    SILC_STR_UI32_STRING("ssh-rsa"),
			    SILC_STR_UI_INT(signature_len),
			    SILC_STR_DATA(signature, signature_len),
			    SILC_STR_END) < 0) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }
  }

  /* Deliver result */
  sign->sign_cb(TRUE, silc_buffer_data(&sig), silc_buffer_len(&sig),
		sign->context);

  silc_buffer_spurge(stack, &sig);
  silc_sfree(stack, sign);
  silc_stack_free(stack);
}
Example #4
0
SilcBool silc_pkcs1_verify(void *public_key,
			   unsigned char *signature,
			   SilcUInt32 signature_len,
			   unsigned char *data,
			   SilcUInt32 data_len,
			   SilcHash hash)
{
  RsaPublicKey *key = public_key;
  SilcBool ret = FALSE;
  SilcMPInt mp_tmp2;
  SilcMPInt mp_dst;
  unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
  SilcUInt32 verify_len, len = (key->bits + 7) / 8;
  SilcBufferStruct di, ldi;
  SilcHash ihash = NULL;
  SilcAsn1 asn1 = NULL;
  char *oid;

  SILC_LOG_DEBUG(("Verify signature"));

  asn1 = silc_asn1_alloc();
  if (!asn1)
    return FALSE;

  silc_mp_init(&mp_tmp2);
  silc_mp_init(&mp_dst);

  /* Format the signature into MP int */
  silc_mp_bin2mp(signature, signature_len, &mp_tmp2);

  /* Verify */
  silc_rsa_public_operation(key, &mp_tmp2, &mp_dst);

  /* MP to data */
  verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);

  /* Unpad data */
  if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
			 unpadded, sizeof(unpadded), &len))
    goto err;
  silc_buffer_set(&di, unpadded, len);

  /* If hash isn't given, allocate the one given in digest info */
  if (!hash) {
    /* Decode digest info */
    if (!silc_asn1_decode(asn1, &di,
			  SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_SEQUENCE,
			      SILC_ASN1_OID(&oid),
			    SILC_ASN1_END,
			  SILC_ASN1_END, SILC_ASN1_END))
      goto err;

    if (!silc_hash_alloc_by_oid(oid, &ihash)) {
      SILC_LOG_DEBUG(("Unknown OID %s", oid));
      goto err;
    }
    hash = ihash;
  }

  /* Hash the data */
  silc_hash_make(hash, data, data_len, hashr);
  data = hashr;
  data_len = silc_hash_len(hash);
  oid = (char *)silc_hash_get_oid(hash);

  /* Encode digest info for comparison */
  memset(&ldi, 0, sizeof(ldi));
  if (!silc_asn1_encode(asn1, &ldi,
			SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_OID(oid),
			    SILC_ASN1_NULL,
			  SILC_ASN1_END,
			  SILC_ASN1_OCTET_STRING(data, data_len),
			SILC_ASN1_END, SILC_ASN1_END))
    goto err;

  SILC_LOG_HEXDUMP(("DigestInfo remote"), silc_buffer_data(&di),
		   silc_buffer_len(&di));
  SILC_LOG_HEXDUMP(("DigestInfo local"), silc_buffer_data(&ldi),
		   silc_buffer_len(&ldi));

  /* Compare */
  if (silc_buffer_len(&di) == silc_buffer_len(&ldi) &&
      !memcmp(silc_buffer_data(&di), silc_buffer_data(&ldi),
	      silc_buffer_len(&ldi)))
    ret = TRUE;

  memset(verify, 0, verify_len);
  memset(unpadded, 0, sizeof(unpadded));
  silc_free(verify);
  silc_mp_uninit(&mp_tmp2);
  silc_mp_uninit(&mp_dst);
  if (hash)
    memset(hashr, 0, sizeof(hashr));
  if (ihash)
    silc_hash_free(ihash);
  silc_asn1_free(asn1);

  return ret;

 err:
  memset(verify, 0, verify_len);
  silc_free(verify);
  silc_mp_uninit(&mp_tmp2);
  silc_mp_uninit(&mp_dst);
  if (ihash)
    silc_hash_free(ihash);
  silc_asn1_free(asn1);
  return FALSE;
}