Пример #1
0
unsigned char *silc_pkcs1_export_public_key(void *public_key,
					    SilcUInt32 *ret_len)
{
  RsaPublicKey *key = public_key;
  SilcAsn1 asn1 = NULL;
  SilcBufferStruct alg_key;
  unsigned char *ret;

  asn1 = silc_asn1_alloc();
  if (!asn1)
    goto err;

  /* Encode to PKCS #1 public key */
  memset(&alg_key, 0, sizeof(alg_key));
  if (!silc_asn1_encode(asn1, &alg_key,
			SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_INT(&key->n),
			  SILC_ASN1_INT(&key->e),
			SILC_ASN1_END, SILC_ASN1_END))
    goto err;

  ret = silc_buffer_steal(&alg_key, ret_len);
  silc_asn1_free(asn1);

  return ret;

 err:
  if (asn1)
    silc_asn1_free(asn1);
  return NULL;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
0
unsigned char *silc_pkcs1_export_private_key(void *private_key,
					     SilcUInt32 *ret_len)
{
  RsaPrivateKey *key = private_key;
  SilcAsn1 asn1;
  SilcBufferStruct alg_key;
  unsigned char *ret;

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

  /* Encode to PKCS #1 private key */
  memset(&alg_key, 0, sizeof(alg_key));
  if (!silc_asn1_encode(asn1, &alg_key,
			SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_SHORT_INT(0),
			  SILC_ASN1_INT(&key->n),
			  SILC_ASN1_INT(&key->e),
			  SILC_ASN1_INT(&key->d),
			  SILC_ASN1_INT(&key->p),
			  SILC_ASN1_INT(&key->q),
			  SILC_ASN1_INT(&key->dP),
			  SILC_ASN1_INT(&key->dQ),
			  SILC_ASN1_INT(&key->qP),
			SILC_ASN1_END, SILC_ASN1_END))
    goto err;

  ret = silc_buffer_steal(&alg_key, ret_len);
  silc_asn1_free(asn1);

  return ret;

 err:
  silc_asn1_free(asn1);
  return NULL;
}
Пример #5
0
int main(int argc, char **argv)
{
  int opt, ret, i;
  SilcAsn1 asn1;
  SilcBufferStruct buf;
  unsigned char *data, *tmp;
  SilcUInt32 data_len;

  if (argc < 2) {
    usage();
    return 1;
  }

  while ((opt = getopt(argc, argv, "hxbai")) != EOF) {
    switch (opt) {
    case 'h':
      usage();
      return 1;
      break;

    case 'x':
      hexdump = TRUE;
      break;

    case 'b':
      dec_base64 = TRUE;
      break;

    case 'i':
      ignore_header = TRUE;
      break;

    case 'a':
      parse_all = TRUE;
      break;

    default:
      usage();
      return 1;
    }
  }

  data = tmp = silc_file_readfile(argv[argc - 1], &data_len, NULL);
  if (!data) {
    fprintf(stderr, "Error: Cannot read file '%s': %s\n", argv[argc - 1],
	    silc_errno_string(silc_errno));
    return 1;
  }

  silc_buffer_set(&buf, data, data_len);

  if (ignore_header) {
    SilcBool header = FALSE;
    for (i = 0; i < data_len; i++) {
      if (data_len > i + 4 &&
	  data[i    ] == '-' && data[i + 1] == '-' &&
	  data[i + 2] == '-' && data[i + 3] == '-') {

	if (data_len > i + 5 && (data[i + 4] == '\r' ||
				 tmp[i + 4] == '\n')) {
	  /* End of line, header */
	  if (data_len > i + 6 && data[i + 4] == '\r' &&
	      data[i + 5] == '\n')
	    i++;
	  i += 5;
	  silc_buffer_pull(&buf, i);
	  header = TRUE;
	} else if (i > 0 && data_len > i + 5 && data[i + 4] != '-' &&
		   header) {
	  /* Start of line, footer */
	  silc_buffer_push_tail(&buf, silc_buffer_truelen(&buf) - i);
	  break;
	}
      }
    }
  }

  if (dec_base64) {
    data = silc_base64_decode(NULL, silc_buffer_data(&buf),
			      silc_buffer_len(&buf), &data_len);
    if (!data) {
      fprintf(stderr, "Error: Cannot decode Base64 encoding\n");
      return 1;
    }
    silc_buffer_set(&buf, data, data_len);
    silc_free(tmp);
  }

  asn1 = silc_asn1_alloc(NULL);

  ret = asn1_dump(asn1, &buf, 0);

  silc_asn1_free(asn1);
  silc_free(data);

  return ret;
}
Пример #6
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);
}
Пример #7
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;
}
Пример #8
0
SilcBool silc_pkcs1_sign(void *private_key,
			 unsigned char *src,
			 SilcUInt32 src_len,
			 unsigned char *signature,
			 SilcUInt32 signature_size,
			 SilcUInt32 *ret_signature_len,
			 SilcBool compute_hash,
			 SilcHash hash)
{
  RsaPrivateKey *key = private_key;
  unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
  SilcMPInt mp_tmp;
  SilcMPInt mp_dst;
  SilcBufferStruct di;
  SilcUInt32 len = (key->bits + 7) / 8;
  const char *oid;
  SilcAsn1 asn1;

  SILC_LOG_DEBUG(("Sign"));

  if (sizeof(padded) < len)
    return FALSE;
  if (signature_size < len)
    return FALSE;

  oid = silc_hash_get_oid(hash);
  if (!oid)
    return FALSE;

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

  /* Compute hash */
  if (compute_hash) {
    silc_hash_make(hash, src, src_len, hashr);
    src = hashr;
    src_len = silc_hash_len(hash);
  }

  /* Encode digest info */
  memset(&di, 0, sizeof(di));
  if (!silc_asn1_encode(asn1, &di,
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_OID(oid),
			    SILC_ASN1_NULL,
			  SILC_ASN1_END,
			  SILC_ASN1_OCTET_STRING(src, src_len),
			SILC_ASN1_END, SILC_ASN1_END)) {
    silc_asn1_free(asn1);
    return FALSE;
  }
  SILC_LOG_HEXDUMP(("DigestInfo"), silc_buffer_data(&di),
		   silc_buffer_len(&di));

  /* Pad data */
  if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, silc_buffer_data(&di),
			 silc_buffer_len(&di), padded, len, NULL)) {
    silc_asn1_free(asn1);
    return FALSE;
  }

  silc_mp_init(&mp_tmp);
  silc_mp_init(&mp_dst);

  /* Data to MP */
  silc_mp_bin2mp(padded, len, &mp_tmp);

  /* Sign */
  silc_rsa_private_operation(key, &mp_tmp, &mp_dst);

  /* MP to data */
  silc_mp_mp2bin_noalloc(&mp_dst, signature, len);
  *ret_signature_len = len;

  memset(padded, 0, sizeof(padded));
  silc_mp_uninit(&mp_tmp);
  silc_mp_uninit(&mp_dst);
  if (compute_hash)
    memset(hashr, 0, sizeof(hashr));
  silc_asn1_free(asn1);

  return TRUE;
}