1295367Sdes/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */ 257429Smarkm/* 357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 557429Smarkm * All rights reserved 660576Skris * 765674Skris * As far as I am concerned, the code I have written for this software 865674Skris * can be used freely for any purpose. Any derived versions of this 965674Skris * software must be clearly marked as such, and if the derived work is 1065674Skris * incompatible with the protocol description in the RFC file, it must be 1165674Skris * called by a name other than "ssh" or "Secure Shell". 1260576Skris * 1376262Sgreen * 1465674Skris * Copyright (c) 1999 Niels Provos. All rights reserved. 1560576Skris * 1665674Skris * Redistribution and use in source and binary forms, with or without 1765674Skris * modification, are permitted provided that the following conditions 1865674Skris * are met: 1965674Skris * 1. Redistributions of source code must retain the above copyright 2065674Skris * notice, this list of conditions and the following disclaimer. 2165674Skris * 2. Redistributions in binary form must reproduce the above copyright 2265674Skris * notice, this list of conditions and the following disclaimer in the 2365674Skris * documentation and/or other materials provided with the distribution. 2465674Skris * 2565674Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2665674Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2765674Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2865674Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2965674Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3065674Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3165674Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3265674Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3365674Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3465674Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3565674Skris * 3665674Skris * 3765674Skris * Description of the RSA algorithm can be found e.g. from the following 3865674Skris * sources: 3965674Skris * 4057429Smarkm * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994. 4160576Skris * 4257429Smarkm * Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to 4357429Smarkm * Computer Security. Prentice-Hall, 1989. 4460576Skris * 4557429Smarkm * Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill, 4657429Smarkm * 1994. 4760576Skris * 4857429Smarkm * R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications 4957429Smarkm * System and Method. US Patent 4,405,829, 1983. 5060576Skris * 5157429Smarkm * Hans Riesel: Prime Numbers and Computer Methods for Factorization. 5257429Smarkm * Birkhauser, 1994. 5360576Skris * 5465674Skris * The RSA Frequently Asked Questions document by RSA Data Security, 5565674Skris * Inc., 1995. 5660576Skris * 5765674Skris * RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as 5865674Skris * included below: 5960576Skris * 6057429Smarkm * [gone - had to be deleted - what a pity] 6165674Skris */ 6257429Smarkm 6357429Smarkm#include "includes.h" 6457429Smarkm 65162856Sdes#include <sys/types.h> 66162856Sdes 67162856Sdes#include <stdarg.h> 68162856Sdes#include <string.h> 69162856Sdes 7057429Smarkm#include "rsa.h" 7176262Sgreen#include "log.h" 72295367Sdes#include "ssherr.h" 7357429Smarkm 74295367Sdesint 7557429Smarkmrsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) 7657429Smarkm{ 77295367Sdes u_char *inbuf = NULL, *outbuf = NULL; 78295367Sdes int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; 7957429Smarkm 8057429Smarkm if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) 81295367Sdes return SSH_ERR_INVALID_ARGUMENT; 8257429Smarkm 8357429Smarkm olen = BN_num_bytes(key->n); 84295367Sdes if ((outbuf = malloc(olen)) == NULL) { 85295367Sdes r = SSH_ERR_ALLOC_FAIL; 86295367Sdes goto out; 87295367Sdes } 8857429Smarkm 8957429Smarkm ilen = BN_num_bytes(in); 90295367Sdes if ((inbuf = malloc(ilen)) == NULL) { 91295367Sdes r = SSH_ERR_ALLOC_FAIL; 92295367Sdes goto out; 93295367Sdes } 9457429Smarkm BN_bn2bin(in, inbuf); 9557429Smarkm 9657429Smarkm if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, 97295367Sdes RSA_PKCS1_PADDING)) <= 0) { 98295367Sdes r = SSH_ERR_LIBCRYPTO_ERROR; 99295367Sdes goto out; 100295367Sdes } 10157429Smarkm 102295367Sdes if (BN_bin2bn(outbuf, len, out) == NULL) { 103295367Sdes r = SSH_ERR_LIBCRYPTO_ERROR; 104295367Sdes goto out; 105295367Sdes } 106295367Sdes r = 0; 10757429Smarkm 108295367Sdes out: 109295367Sdes if (outbuf != NULL) { 110295367Sdes explicit_bzero(outbuf, olen); 111295367Sdes free(outbuf); 112295367Sdes } 113295367Sdes if (inbuf != NULL) { 114295367Sdes explicit_bzero(inbuf, ilen); 115295367Sdes free(inbuf); 116295367Sdes } 117295367Sdes return r; 11857429Smarkm} 11957429Smarkm 12072397Skrisint 12157429Smarkmrsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) 12257429Smarkm{ 123295367Sdes u_char *inbuf = NULL, *outbuf = NULL; 124295367Sdes int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; 12557429Smarkm 12657429Smarkm olen = BN_num_bytes(key->n); 127295367Sdes if ((outbuf = malloc(olen)) == NULL) { 128295367Sdes r = SSH_ERR_ALLOC_FAIL; 129295367Sdes goto out; 130295367Sdes } 13157429Smarkm 13257429Smarkm ilen = BN_num_bytes(in); 133295367Sdes if ((inbuf = malloc(ilen)) == NULL) { 134295367Sdes r = SSH_ERR_ALLOC_FAIL; 135295367Sdes goto out; 136295367Sdes } 13757429Smarkm BN_bn2bin(in, inbuf); 13857429Smarkm 13957429Smarkm if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, 14072397Skris RSA_PKCS1_PADDING)) <= 0) { 141295367Sdes r = SSH_ERR_LIBCRYPTO_ERROR; 142295367Sdes goto out; 143295367Sdes } else if (BN_bin2bn(outbuf, len, out) == NULL) { 144295367Sdes r = SSH_ERR_LIBCRYPTO_ERROR; 145295367Sdes goto out; 14672397Skris } 147295367Sdes r = 0; 148295367Sdes out: 149295367Sdes if (outbuf != NULL) { 150295367Sdes explicit_bzero(outbuf, olen); 151295367Sdes free(outbuf); 152295367Sdes } 153295367Sdes if (inbuf != NULL) { 154295367Sdes explicit_bzero(inbuf, ilen); 155295367Sdes free(inbuf); 156295367Sdes } 157295367Sdes return r; 15857429Smarkm} 15957429Smarkm 16092559Sdes/* calculate p-1 and q-1 */ 161295367Sdesint 16292559Sdesrsa_generate_additional_parameters(RSA *rsa) 16357429Smarkm{ 164295367Sdes BIGNUM *aux = NULL; 165295367Sdes BN_CTX *ctx = NULL; 166295367Sdes int r; 16776262Sgreen 16892559Sdes if ((ctx = BN_CTX_new()) == NULL) 169295367Sdes return SSH_ERR_ALLOC_FAIL; 170295367Sdes if ((aux = BN_new()) == NULL) { 171295367Sdes r = SSH_ERR_ALLOC_FAIL; 172295367Sdes goto out; 173295367Sdes } 17492559Sdes 175164149Sdes if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || 176164149Sdes (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || 177164149Sdes (BN_sub(aux, rsa->p, BN_value_one()) == 0) || 178295367Sdes (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) { 179295367Sdes r = SSH_ERR_LIBCRYPTO_ERROR; 180295367Sdes goto out; 181295367Sdes } 182295367Sdes r = 0; 183295367Sdes out: 18476262Sgreen BN_clear_free(aux); 18576262Sgreen BN_CTX_free(ctx); 186295367Sdes return r; 18757429Smarkm} 18876262Sgreen 189