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; }
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; }
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; }
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; }
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); }