155714Skris/* evp_pkey.c */
2280304Sjkim/*
3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4280304Sjkim * 1999.
555714Skris */
655714Skris/* ====================================================================
7238405Sjkim * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
855714Skris *
955714Skris * Redistribution and use in source and binary forms, with or without
1055714Skris * modification, are permitted provided that the following conditions
1155714Skris * are met:
1255714Skris *
1355714Skris * 1. Redistributions of source code must retain the above copyright
14280304Sjkim *    notice, this list of conditions and the following disclaimer.
1555714Skris *
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in
1855714Skris *    the documentation and/or other materials provided with the
1955714Skris *    distribution.
2055714Skris *
2155714Skris * 3. All advertising materials mentioning features or use of this
2255714Skris *    software must display the following acknowledgment:
2355714Skris *    "This product includes software developed by the OpenSSL Project
2455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2555714Skris *
2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2755714Skris *    endorse or promote products derived from this software without
2855714Skris *    prior written permission. For written permission, please contact
2955714Skris *    licensing@OpenSSL.org.
3055714Skris *
3155714Skris * 5. Products derived from this software may not be called "OpenSSL"
3255714Skris *    nor may "OpenSSL" appear in their names without prior written
3355714Skris *    permission of the OpenSSL Project.
3455714Skris *
3555714Skris * 6. Redistributions of any form whatsoever must retain the following
3655714Skris *    acknowledgment:
3755714Skris *    "This product includes software developed by the OpenSSL Project
3855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3955714Skris *
4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5255714Skris * ====================================================================
5355714Skris *
5455714Skris * This product includes cryptographic software written by Eric Young
5555714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5655714Skris * Hudson (tjh@cryptsoft.com).
5755714Skris *
5855714Skris */
5955714Skris
6055714Skris#include <stdio.h>
6155714Skris#include <stdlib.h>
6255714Skris#include "cryptlib.h"
6355714Skris#include <openssl/x509.h>
6455714Skris#include <openssl/rand.h>
65238405Sjkim#include "asn1_locl.h"
6655714Skris
6755714Skris/* Extract a private key from a PKCS8 structure */
6855714Skris
69160814SsimonEVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8)
7055714Skris{
71280304Sjkim    EVP_PKEY *pkey = NULL;
72280304Sjkim    ASN1_OBJECT *algoid;
73280304Sjkim    char obj_tmp[80];
7455714Skris
75280304Sjkim    if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8))
76280304Sjkim        return NULL;
77238405Sjkim
78280304Sjkim    if (!(pkey = EVP_PKEY_new())) {
79280304Sjkim        EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE);
80280304Sjkim        return NULL;
81280304Sjkim    }
8259191Skris
83280304Sjkim    if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
84280304Sjkim        EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
85280304Sjkim        i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
86280304Sjkim        ERR_add_error_data(2, "TYPE=", obj_tmp);
87280304Sjkim        goto error;
88280304Sjkim    }
89160814Ssimon
90280304Sjkim    if (pkey->ameth->priv_decode) {
91280304Sjkim        if (!pkey->ameth->priv_decode(pkey, p8)) {
92280304Sjkim            EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_PRIVATE_KEY_DECODE_ERROR);
93280304Sjkim            goto error;
94280304Sjkim        }
95280304Sjkim    } else {
96280304Sjkim        EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_METHOD_NOT_SUPPORTED);
97280304Sjkim        goto error;
98280304Sjkim    }
99160814Ssimon
100280304Sjkim    return pkey;
101160814Ssimon
102280304Sjkim error:
103280304Sjkim    EVP_PKEY_free(pkey);
104280304Sjkim    return NULL;
10555714Skris}
10655714Skris
10759191SkrisPKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey)
10859191Skris{
109280304Sjkim    return EVP_PKEY2PKCS8_broken(pkey, PKCS8_OK);
11059191Skris}
11159191Skris
11255714Skris/* Turn a private key into a PKCS8 structure */
11355714Skris
11459191SkrisPKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
11555714Skris{
116280304Sjkim    PKCS8_PRIV_KEY_INFO *p8;
11759191Skris
118280304Sjkim    if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) {
119280304Sjkim        EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, ERR_R_MALLOC_FAILURE);
120280304Sjkim        return NULL;
121280304Sjkim    }
122280304Sjkim    p8->broken = broken;
12355714Skris
124280304Sjkim    if (pkey->ameth) {
125280304Sjkim        if (pkey->ameth->priv_encode) {
126280304Sjkim            if (!pkey->ameth->priv_encode(p8, pkey)) {
127280304Sjkim                EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,
128280304Sjkim                       EVP_R_PRIVATE_KEY_ENCODE_ERROR);
129280304Sjkim                goto error;
130280304Sjkim            }
131280304Sjkim        } else {
132280304Sjkim            EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, EVP_R_METHOD_NOT_SUPPORTED);
133280304Sjkim            goto error;
134280304Sjkim        }
135280304Sjkim    } else {
136280304Sjkim        EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,
137280304Sjkim               EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
138280304Sjkim        goto error;
139280304Sjkim    }
140280304Sjkim    RAND_add(p8->pkey->value.octet_string->data,
141280304Sjkim             p8->pkey->value.octet_string->length, 0.0);
142280304Sjkim    return p8;
143280304Sjkim error:
144280304Sjkim    PKCS8_PRIV_KEY_INFO_free(p8);
145280304Sjkim    return NULL;
14655714Skris}
14755714Skris
14855714SkrisPKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken)
14955714Skris{
150280304Sjkim    switch (broken) {
15155714Skris
152280304Sjkim    case PKCS8_OK:
153280304Sjkim        p8->broken = PKCS8_OK;
154280304Sjkim        return p8;
155280304Sjkim        break;
15655714Skris
157280304Sjkim    case PKCS8_NO_OCTET:
158280304Sjkim        p8->broken = PKCS8_NO_OCTET;
159280304Sjkim        p8->pkey->type = V_ASN1_SEQUENCE;
160280304Sjkim        return p8;
161280304Sjkim        break;
16255714Skris
163280304Sjkim    default:
164280304Sjkim        EVPerr(EVP_F_PKCS8_SET_BROKEN, EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE);
165280304Sjkim        return NULL;
166280304Sjkim    }
16755714Skris}
16855714Skris
169160814Ssimon/* EVP_PKEY attribute functions */
170160814Ssimon
171160814Ssimonint EVP_PKEY_get_attr_count(const EVP_PKEY *key)
172160814Ssimon{
173280304Sjkim    return X509at_get_attr_count(key->attributes);
174160814Ssimon}
175160814Ssimon
176280304Sjkimint EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos)
177160814Ssimon{
178280304Sjkim    return X509at_get_attr_by_NID(key->attributes, nid, lastpos);
179160814Ssimon}
180160814Ssimon
181160814Ssimonint EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj,
182280304Sjkim                             int lastpos)
183160814Ssimon{
184280304Sjkim    return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos);
185160814Ssimon}
186160814Ssimon
187160814SsimonX509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc)
188160814Ssimon{
189280304Sjkim    return X509at_get_attr(key->attributes, loc);
190160814Ssimon}
191160814Ssimon
192160814SsimonX509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc)
193160814Ssimon{
194280304Sjkim    return X509at_delete_attr(key->attributes, loc);
195160814Ssimon}
196160814Ssimon
197160814Ssimonint EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr)
198160814Ssimon{
199280304Sjkim    if (X509at_add1_attr(&key->attributes, attr))
200280304Sjkim        return 1;
201280304Sjkim    return 0;
202160814Ssimon}
203160814Ssimon
204160814Ssimonint EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
205280304Sjkim                              const ASN1_OBJECT *obj, int type,
206280304Sjkim                              const unsigned char *bytes, int len)
207160814Ssimon{
208280304Sjkim    if (X509at_add1_attr_by_OBJ(&key->attributes, obj, type, bytes, len))
209280304Sjkim        return 1;
210280304Sjkim    return 0;
211160814Ssimon}
212160814Ssimon
213160814Ssimonint EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
214280304Sjkim                              int nid, int type,
215280304Sjkim                              const unsigned char *bytes, int len)
216160814Ssimon{
217280304Sjkim    if (X509at_add1_attr_by_NID(&key->attributes, nid, type, bytes, len))
218280304Sjkim        return 1;
219280304Sjkim    return 0;
220160814Ssimon}
221160814Ssimon
222160814Ssimonint EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
223280304Sjkim                              const char *attrname, int type,
224280304Sjkim                              const unsigned char *bytes, int len)
225160814Ssimon{
226280304Sjkim    if (X509at_add1_attr_by_txt(&key->attributes, attrname, type, bytes, len))
227280304Sjkim        return 1;
228280304Sjkim    return 0;
229160814Ssimon}
230