p12_mutl.c revision 280304
1457SN/A/* p12_mutl.c */
22453Sihse/*
3457SN/A * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4457SN/A * 1999.
5457SN/A */
6457SN/A/* ====================================================================
7457SN/A * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
8457SN/A *
9457SN/A * Redistribution and use in source and binary forms, with or without
10457SN/A * modification, are permitted provided that the following conditions
11457SN/A * are met:
12457SN/A *
13457SN/A * 1. Redistributions of source code must retain the above copyright
14457SN/A *    notice, this list of conditions and the following disclaimer.
15457SN/A *
16457SN/A * 2. Redistributions in binary form must reproduce the above copyright
17457SN/A *    notice, this list of conditions and the following disclaimer in
18457SN/A *    the documentation and/or other materials provided with the
19457SN/A *    distribution.
20457SN/A *
21457SN/A * 3. All advertising materials mentioning features or use of this
22457SN/A *    software must display the following acknowledgment:
23457SN/A *    "This product includes software developed by the OpenSSL Project
24457SN/A *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25457SN/A *
261410Sihse * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
271410Sihse *    endorse or promote products derived from this software without
281410Sihse *    prior written permission. For written permission, please contact
291410Sihse *    licensing@OpenSSL.org.
301410Sihse *
31457SN/A * 5. Products derived from this software may not be called "OpenSSL"
321410Sihse *    nor may "OpenSSL" appear in their names without prior written
331410Sihse *    permission of the OpenSSL Project.
34457SN/A *
351410Sihse * 6. Redistributions of any form whatsoever must retain the following
362518Sihse *    acknowledgment:
372518Sihse *    "This product includes software developed by the OpenSSL Project
382518Sihse *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
392518Sihse *
402518Sihse * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
411410Sihse * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
421410Sihse * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
431410Sihse * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
441410Sihse * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
451410Sihse * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46492SN/A * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
471410Sihse * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
482518Sihse * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
492518Sihse * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50492SN/A * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
511410Sihse * OF THE POSSIBILITY OF SUCH DAMAGE.
521410Sihse * ====================================================================
53492SN/A *
541410Sihse * This product includes cryptographic software written by Eric Young
551410Sihse * (eay@cryptsoft.com).  This product includes software written by Tim
561410Sihse * Hudson (tjh@cryptsoft.com).
571410Sihse *
581410Sihse */
59492SN/A
601410Sihse#ifndef OPENSSL_NO_HMAC
611410Sihse# include <stdio.h>
621651Sihse# include "cryptlib.h"
631410Sihse# include <openssl/hmac.h>
641410Sihse# include <openssl/rand.h>
651426Sihse# include <openssl/pkcs12.h>
661426Sihse
671651Sihse/* Generate a MAC */
681651Sihseint PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
691651Sihse                   unsigned char *mac, unsigned int *maclen)
70492SN/A{
711426Sihse    const EVP_MD *md_type;
721426Sihse    HMAC_CTX hmac;
731426Sihse    unsigned char key[EVP_MAX_MD_SIZE], *salt;
741426Sihse    int saltlen, iter;
751426Sihse    int md_size;
761426Sihse
771410Sihse    if (!PKCS7_type_is_data(p12->authsafes)) {
781410Sihse        PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_CONTENT_TYPE_NOT_DATA);
791410Sihse        return 0;
801410Sihse    }
811410Sihse
821426Sihse    salt = p12->mac->salt->data;
831426Sihse    saltlen = p12->mac->salt->length;
841410Sihse    if (!p12->mac->iter)
851410Sihse        iter = 1;
861410Sihse    else
871410Sihse        iter = ASN1_INTEGER_get(p12->mac->iter);
881410Sihse    if (!(md_type = EVP_get_digestbyobj(p12->mac->dinfo->algor->algorithm))) {
891410Sihse        PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
901410Sihse        return 0;
911410Sihse    }
92492SN/A    md_size = EVP_MD_size(md_type);
931410Sihse    if (md_size < 0)
941410Sihse        return 0;
951410Sihse    if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter,
961410Sihse                        md_size, key, md_type)) {
971410Sihse        PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR);
981410Sihse        return 0;
991410Sihse    }
1001410Sihse    HMAC_CTX_init(&hmac);
1011410Sihse    if (!HMAC_Init_ex(&hmac, key, md_size, md_type, NULL)
1021410Sihse        || !HMAC_Update(&hmac, p12->authsafes->d.data->data,
1031410Sihse                        p12->authsafes->d.data->length)
104492SN/A        || !HMAC_Final(&hmac, mac, maclen)) {
1051410Sihse        HMAC_CTX_cleanup(&hmac);
1061410Sihse        return 0;
1071410Sihse    }
1081410Sihse    HMAC_CTX_cleanup(&hmac);
1091410Sihse    return 1;
1101410Sihse}
1111410Sihse
1121410Sihse/* Verify the mac */
1131410Sihseint PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
1141410Sihse{
1151410Sihse    unsigned char mac[EVP_MAX_MD_SIZE];
1161410Sihse    unsigned int maclen;
117492SN/A    if (p12->mac == NULL) {
1181410Sihse        PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_ABSENT);
1191410Sihse        return 0;
1201410Sihse    }
1211410Sihse    if (!PKCS12_gen_mac(p12, pass, passlen, mac, &maclen)) {
1221410Sihse        PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_GENERATION_ERROR);
1231410Sihse        return 0;
1241410Sihse    }
1251410Sihse    if ((maclen != (unsigned int)p12->mac->dinfo->digest->length)
1261410Sihse        || memcmp(mac, p12->mac->dinfo->digest->data, maclen))
1271410Sihse        return 0;
128492SN/A    return 1;
1291915Sihse}
1301915Sihse
1311915Sihse/* Set a mac */
1321915Sihse
1331915Sihseint PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
1341915Sihse                   unsigned char *salt, int saltlen, int iter,
1351915Sihse                   const EVP_MD *md_type)
1361915Sihse{
1371915Sihse    unsigned char mac[EVP_MAX_MD_SIZE];
1381915Sihse    unsigned int maclen;
1391915Sihse
1401915Sihse    if (!md_type)
1411915Sihse        md_type = EVP_sha1();
1421915Sihse    if (PKCS12_setup_mac(p12, iter, salt, saltlen, md_type) == PKCS12_ERROR) {
1431915Sihse        PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_SETUP_ERROR);
1441915Sihse        return 0;
1451915Sihse    }
1461410Sihse    if (!PKCS12_gen_mac(p12, pass, passlen, mac, &maclen)) {
1471410Sihse        PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_GENERATION_ERROR);
1481410Sihse        return 0;
1491410Sihse    }
1501410Sihse    if (!(M_ASN1_OCTET_STRING_set(p12->mac->dinfo->digest, mac, maclen))) {
1511410Sihse        PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_STRING_SET_ERROR);
152492SN/A        return 0;
1531410Sihse    }
154505SN/A    return 1;
155837SN/A}
1561915Sihse
1571915Sihse/* Set up a mac structure */
1581915Sihseint PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
1591915Sihse                     const EVP_MD *md_type)
1601915Sihse{
1612535Sasemenyuk    if (!(p12->mac = PKCS12_MAC_DATA_new()))
1622535Sasemenyuk        return PKCS12_ERROR;
1632535Sasemenyuk    if (iter > 1) {
1642535Sasemenyuk        if (!(p12->mac->iter = M_ASN1_INTEGER_new())) {
1652535Sasemenyuk            PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
1662535Sasemenyuk            return 0;
1672535Sasemenyuk        }
1682535Sasemenyuk        if (!ASN1_INTEGER_set(p12->mac->iter, iter)) {
1692535Sasemenyuk            PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
1702535Sasemenyuk            return 0;
1712535Sasemenyuk        }
1722535Sasemenyuk    }
1731915Sihse    if (!saltlen)
174476SN/A        saltlen = PKCS12_SALT_LEN;
175837SN/A    p12->mac->salt->length = saltlen;
1761410Sihse    if (!(p12->mac->salt->data = OPENSSL_malloc(saltlen))) {
1771410Sihse        PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
178837SN/A        return 0;
1791410Sihse    }
1801410Sihse    if (!salt) {
1811410Sihse        if (RAND_pseudo_bytes(p12->mac->salt->data, saltlen) < 0)
1821410Sihse            return 0;
1831410Sihse    } else
1841410Sihse        memcpy(p12->mac->salt->data, salt, saltlen);
1851410Sihse    p12->mac->dinfo->algor->algorithm = OBJ_nid2obj(EVP_MD_type(md_type));
1861410Sihse    if (!(p12->mac->dinfo->algor->parameter = ASN1_TYPE_new())) {
1871862Serikj        PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
188457SN/A        return 0;
1891915Sihse    }
1902535Sasemenyuk    p12->mac->dinfo->algor->parameter->type = V_ASN1_NULL;
1911915Sihse
1921410Sihse    return 1;
193457SN/A}
1941410Sihse#endif
195457SN/A