SilcBool silc_pkcs1_sign_no_oid(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; SilcMPInt mp_tmp; SilcMPInt mp_dst; unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN]; SilcUInt32 len = (key->bits + 7) / 8; SILC_LOG_DEBUG(("Sign")); if (sizeof(padded) < len) return FALSE; if (signature_size < len) return FALSE; /* Compute hash if requested */ if (compute_hash) { silc_hash_make(hash, src, src_len, hashr); src = hashr; src_len = silc_hash_len(hash); } /* Pad data */ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len, padded, len, NULL)) 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)); return TRUE; }
unsigned char *silc_mp_mp2bin(SilcMPInt *val, SilcUInt32 len, SilcUInt32 *ret_len) { SilcUInt32 size; unsigned char *ret; size = (len ? len : ((silc_mp_sizeinbase(val, 2) + 7) / 8)); ret = silc_calloc(size, sizeof(*ret)); if (!ret) return NULL; silc_mp_mp2bin_noalloc(val, ret, size); if (ret_len) *ret_len = size; return ret; }
SilcBool silc_pkcs1_encrypt(void *public_key, unsigned char *src, SilcUInt32 src_len, unsigned char *dst, SilcUInt32 dst_size, SilcUInt32 *ret_dst_len, SilcRng rng) { RsaPublicKey *key = public_key; SilcMPInt mp_tmp; SilcMPInt mp_dst; unsigned char padded[2048 + 1]; SilcUInt32 len = (key->bits + 7) / 8; if (sizeof(padded) < len) return FALSE; if (dst_size < len) return FALSE; /* Pad data */ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len, padded, len, rng)) return FALSE; silc_mp_init(&mp_tmp); silc_mp_init(&mp_dst); /* Data to MP */ silc_mp_bin2mp(padded, len, &mp_tmp); /* Encrypt */ silc_rsa_public_operation(key, &mp_tmp, &mp_dst); /* MP to data */ silc_mp_mp2bin_noalloc(&mp_dst, dst, len); *ret_dst_len = len; memset(padded, 0, sizeof(padded)); silc_mp_uninit(&mp_tmp); silc_mp_uninit(&mp_dst); return TRUE; }
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); }
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; }