1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * project 2006.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ====================================================================
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the documentation and/or other materials provided with the
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    distribution.
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    software must display the following acknowledgment:
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    endorse or promote products derived from this software without
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    prior written permission. For written permission, please contact
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    licensing@OpenSSL.org.
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL"
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    nor may "OpenSSL" appear in their names without prior written
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    permission of the OpenSSL Project.
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    acknowledgment:
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ====================================================================
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). */
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/evp.h>
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1.h>
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1t.h>
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/digest.h>
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/obj.h>
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/rsa.h>
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/x509.h>
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "../rsa/internal.h"
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h"
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *encoded = NULL;
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int len;
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  len = i2d_RSAPublicKey(pkey->pkey.rsa, &encoded);
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (len <= 0) {
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA), V_ASN1_NULL, NULL,
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                              encoded, len)) {
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_free(encoded);
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const uint8_t *p;
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int pklen;
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA *rsa;
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey)) {
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa = d2i_RSAPublicKey(NULL, &p, pklen);
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (rsa == NULL) {
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_pub_decode, ERR_R_RSA_LIB);
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY_assign_RSA(pkey, rsa);
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) == 0 &&
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley         BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) == 0;
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *rk = NULL;
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int rklen;
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (rklen <= 0) {
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_priv_encode, ERR_R_MALLOC_FAILURE);
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* TODO(fork): const correctness in next line. */
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_rsaEncryption), 0,
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                       V_ASN1_NULL, NULL, rk, rklen)) {
125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_priv_encode, ERR_R_MALLOC_FAILURE);
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const uint8_t *p;
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int pklen;
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA *rsa;
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8)) {
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_priv_decode, ERR_R_MALLOC_FAILURE);
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (rsa == NULL) {
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_priv_decode, ERR_R_RSA_LIB);
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY_assign_RSA(pkey, rsa);
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
152d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_opaque(const EVP_PKEY *pkey) {
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return RSA_is_opaque(pkey->pkey.rsa);
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
156d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return RSA_supports_digest(pkey->pkey.rsa, md);
158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
160d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int int_rsa_size(const EVP_PKEY *pkey) {
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return RSA_size(pkey->pkey.rsa);
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_bits(const EVP_PKEY *pkey) {
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return BN_num_bits(pkey->pkey.rsa->n);
166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void update_buflen(const BIGNUM *b, size_t *pbuflen) {
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t i;
172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!b) {
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  i = BN_num_bytes(b);
178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (*pbuflen < i) {
179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    *pbuflen = i;
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_rsa_print(BIO *out, const RSA *rsa, int off,
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                        int include_private) {
185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  char *str;
186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const char *s;
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *m = NULL;
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ret = 0, mod_len = 0;
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t buf_len = 0;
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  update_buflen(rsa->n, &buf_len);
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  update_buflen(rsa->e, &buf_len);
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (include_private) {
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    update_buflen(rsa->d, &buf_len);
196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    update_buflen(rsa->p, &buf_len);
197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    update_buflen(rsa->q, &buf_len);
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    update_buflen(rsa->dmp1, &buf_len);
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    update_buflen(rsa->dmq1, &buf_len);
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    update_buflen(rsa->iqmp, &buf_len);
201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (m == NULL) {
205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, do_rsa_print, ERR_R_MALLOC_FAILURE);
206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (rsa->n != NULL) {
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mod_len = BN_num_bits(rsa->n);
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!BIO_indent(out, off, 128)) {
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (include_private && rsa->d) {
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    str = "modulus:";
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    s = "publicExponent:";
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    str = "Modulus:";
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    s = "Exponent:";
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !ASN1_bn_print(out, s, rsa->e, m, off)) {
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (include_private) {
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        !ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        !ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        !ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        !ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        !ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret = 1;
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
248e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  OPENSSL_free(m);
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
252d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                         ASN1_PCTX *ctx) {
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
258d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                          ASN1_PCTX *ctx) {
260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const uint8_t *p;
266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int plen;
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (alg == NULL ||
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      alg->parameter->type != V_ASN1_SEQUENCE) {
271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  p = alg->parameter->value.sequence->data;
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  plen = alg->parameter->value.sequence->length;
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return d2i_X509_ALGOR(NULL, &p, plen);
277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
279d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                                      X509_ALGOR **pmaskHash) {
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const uint8_t *p;
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int plen;
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA_PSS_PARAMS *pss;
284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *pmaskHash = NULL;
286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE) {
288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  p = alg->parameter->value.sequence->data;
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  plen = alg->parameter->value.sequence->length;
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!pss) {
295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return pss;
301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
303d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                               X509_ALGOR *maskHash, int indent) {
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int rv = 0;
306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!pss) {
308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (BIO_puts(bp, "\n") <= 0 ||
315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !BIO_indent(bp, indent, 128) ||
316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      BIO_puts(bp, "Hash Algorithm: ") <= 0) {
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pss->hashAlgorithm) {
321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (BIO_puts(bp, "\n") <= 0 ||
329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !BIO_indent(bp, indent, 128) ||
330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      BIO_puts(bp, "Mask Algorithm: ") <= 0) {
331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pss->maskGenAlgorithm) {
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        BIO_puts(bp, " with ") <= 0) {
337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (maskHash) {
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        goto err;
343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else if (BIO_puts(bp, "INVALID") <= 0) {
345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIO_puts(bp, "\n");
351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!BIO_indent(bp, indent, 128) ||
353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      BIO_puts(bp, "Salt Length: 0x") <= 0) {
354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pss->saltLength) {
358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else if (BIO_puts(bp, "14 (default)") <= 0) {
362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIO_puts(bp, "\n");
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!BIO_indent(bp, indent, 128) ||
367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      BIO_puts(bp, "Trailer Field: 0x") <= 0) {
368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pss->trailerField) {
372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else if (BIO_puts(bp, "BC (default)") <= 0) {
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIO_puts(bp, "\n");
379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rv = 1;
381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
382d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return rv;
384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
386d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                         const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss) {
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    int rv;
390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    RSA_PSS_PARAMS *pss;
391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    X509_ALGOR *maskHash;
392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    pss = rsa_pss_decode(sigalg, &maskHash);
394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    rv = rsa_pss_param_print(bp, pss, maskHash, indent);
395e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    RSA_PSS_PARAMS_free(pss);
396e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    X509_ALGOR_free(maskHash);
397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!rv) {
398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else if (!sig && BIO_puts(bp, "\n") <= 0) {
401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (sig) {
405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return X509_signature_dump(bp, sig, indent);
406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
410d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int old_rsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder,
411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                               int derlen) {
412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (rsa == NULL) {
414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, old_rsa_priv_decode, ERR_R_RSA_LIB);
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY_assign_RSA(pkey, rsa);
418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
421d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) {
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* allocate and set algorithm ID from EVP_MD, default SHA1 */
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (EVP_MD_type(md) == NID_sha1) {
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *palg = X509_ALGOR_new();
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!*palg) {
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  X509_ALGOR_set_md(*palg, md);
435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Allocate and set MGF1 algorithm ID from EVP_MD */
439d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  X509_ALGOR *algtmp = NULL;
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ASN1_STRING *stmp = NULL;
442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *palg = NULL;
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (EVP_MD_type(mgf1md) == NID_sha1) {
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* need to embed algorithm ID inside another */
448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!rsa_md_to_algor(&algtmp, mgf1md) ||
449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *palg = X509_ALGOR_new();
453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!*palg) {
454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  stmp = NULL;
458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
459d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
460e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ASN1_STRING_free(stmp);
461e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  X509_ALGOR_free(algtmp);
462e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (*palg) {
463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
464e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 0;
467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* convert algorithm ID to EVP_MD, default SHA1 */
470d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EVP_MD *md;
472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!alg) {
473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return EVP_sha1();
474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  md = EVP_get_digestbyobj(alg->algorithm);
476d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (md == NULL) {
477d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_algor_to_md, EVP_R_UNKNOWN_DIGEST);
478d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
479d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return md;
480d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
481d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
482d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
483d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
484d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EVP_MD *md;
485d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!alg) {
486d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return EVP_sha1();
487d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
488d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Check mask and lookup mask hash algorithm */
489d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
490d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_mgf1_to_md, EVP_R_UNSUPPORTED_MASK_ALGORITHM);
491d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
492d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
493d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!maskHash) {
494d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_mgf1_to_md, EVP_R_UNSUPPORTED_MASK_PARAMETER);
495d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
496d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
497d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  md = EVP_get_digestbyobj(maskHash->algorithm);
498d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (md == NULL) {
499d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_mgf1_to_md, EVP_R_UNKNOWN_MASK_DIGEST);
500d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
501d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
502d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return md;
503d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
504d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
505d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* rsa_ctx_to_pss converts EVP_PKEY_CTX in PSS mode into corresponding
506d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * algorithm parameter, suitable for setting as an AlgorithmIdentifier. */
507d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) {
508d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EVP_MD *sigmd, *mgf1md;
509d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA_PSS_PARAMS *pss = NULL;
510d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ASN1_STRING *os = NULL;
511d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
512d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int saltlen, rv = 0;
513d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
514e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) ||
515e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) ||
516d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) {
517d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
518d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
519d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
520d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (saltlen == -1) {
521d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    saltlen = EVP_MD_size(sigmd);
522d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else if (saltlen == -2) {
523d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
524d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
525d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      saltlen--;
526d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
527d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
528d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
529d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
530d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
531d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  pss = RSA_PSS_PARAMS_new();
532d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!pss) {
533d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
534d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
535d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
536d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (saltlen != 20) {
537d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    pss->saltLength = ASN1_INTEGER_new();
538d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!pss->saltLength ||
539d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
540d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
541d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
542d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
543d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
544d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
545d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
546d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
547d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
548d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
549d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Finally create string with pss parameter encoding. */
550d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
551d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
552d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
553d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rv = 1;
554d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
555d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
556e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (pss) {
557d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    RSA_PSS_PARAMS_free(pss);
558e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
559e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (rv) {
560d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return os;
561e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
562e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (os) {
563d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ASN1_STRING_free(os);
564e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
565d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return NULL;
566d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
567d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
568d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* From PSS AlgorithmIdentifier set public key parameters. */
569d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
570d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ret = 0;
571d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int saltlen;
572d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EVP_MD *mgf1md = NULL, *md = NULL;
573d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA_PSS_PARAMS *pss;
574d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  X509_ALGOR *maskHash;
575d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY_CTX *pkctx;
576d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
577d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Sanity check: make sure it is PSS */
578d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
579d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
580d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
581d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
582d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Decode PSS parameters */
583d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  pss = rsa_pss_decode(sigalg, &maskHash);
584d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pss == NULL) {
585d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_PSS_PARAMETERS);
586d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
587d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
588d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
589d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
590d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!mgf1md) {
591d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
592d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
593d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  md = rsa_algor_to_md(pss->hashAlgorithm);
594d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!md) {
595d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
596d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
597d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
598d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  saltlen = 20;
599d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pss->saltLength) {
600d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    saltlen = ASN1_INTEGER_get(pss->saltLength);
601d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
602d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* Could perform more salt length sanity checks but the main
603d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * RSA routines will trap other invalid values anyway. */
604d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (saltlen < 0) {
605d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_SALT_LENGTH);
606d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
607d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
608d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
609d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
610d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* low-level routines support only trailer field 0xbc (value 1)
611d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * and PKCS#1 says we should reject any other value anyway. */
612d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
613d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_TRAILER);
614d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
615d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
616d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
617d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
618e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
619e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
620e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
621d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
622d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
623d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
624d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret = 1;
625d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
626d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
627d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA_PSS_PARAMS_free(pss);
628d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (maskHash) {
629d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    X509_ALGOR_free(maskHash);
630d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
631d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
632d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
633d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
634d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Customised RSA AlgorithmIdentifier handling. This is called when a signature
635d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * is encountered requiring special handling. We currently only handle PSS. */
636d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int rsa_digest_verify_init_from_algorithm(EVP_MD_CTX *ctx,
637d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                                                 X509_ALGOR *sigalg,
638d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                                                 EVP_PKEY *pkey) {
639d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Sanity check: make sure it is PSS */
640d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
641d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EVP, rsa_digest_verify_init_from_algorithm,
642d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                      EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
643d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
644d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
645d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return rsa_pss_to_ctx(ctx, sigalg, pkey);
646d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
647d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
648d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic evp_digest_sign_algorithm_result_t rsa_digest_sign_algorithm(
649d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    EVP_MD_CTX *ctx, X509_ALGOR *sigalg) {
650d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int pad_mode;
651d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY_CTX *pkctx = ctx->pctx;
652e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode)) {
653d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
654d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
655d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (pad_mode == RSA_PKCS1_PSS_PADDING) {
656d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ASN1_STRING *os1 = rsa_ctx_to_pss(pkctx);
657d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!os1) {
658d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
659d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
660d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    X509_ALGOR_set0(sigalg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os1);
661d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return EVP_DIGEST_SIGN_ALGORITHM_SUCCESS;
662d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
663d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
664d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Other padding schemes use the default behavior. */
665d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return EVP_DIGEST_SIGN_ALGORITHM_DEFAULT;
666d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
667d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
668d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyconst EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
669d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY_RSA,
670d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_PKEY_RSA,
671d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ASN1_PKEY_SIGPARAM_NULL,
672d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
673d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  "RSA",
674d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  "OpenSSL RSA method",
675d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
676d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_pub_decode,
677d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_pub_encode,
678d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_pub_cmp,
679d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_pub_print,
680d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
681d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_priv_decode,
682d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_priv_encode,
683d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_priv_print,
684d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
685d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_opaque,
686d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_supports_digest,
687d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
688d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int_rsa_size,
689d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_bits,
690d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
691d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  0,0,0,0,0,0,
692d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
693d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_sig_print,
694d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int_rsa_free,
695d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
696d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  old_rsa_priv_decode,
697d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  old_rsa_priv_encode,
698d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
699d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_digest_verify_init_from_algorithm,
700d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  rsa_digest_sign_algorithm,
701d9e397b599b13d642138480a28c14db7a136bf0Adam Langley};
702