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