1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
   2  * project 2007.
   3  */
   4 /* ====================================================================
   5  * Copyright (c) 2007 The OpenSSL Project.  All rights reserved.
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  *
  11  * 1. Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  *
  14  * 2. Redistributions in binary form must reproduce the above copyright
  15  *    notice, this list of conditions and the following disclaimer in
  16  *    the documentation and/or other materials provided with the
  17  *    distribution.
  18  *
  19  * 3. All advertising materials mentioning features or use of this
  20  *    software must display the following acknowledgment:
  21  *    "This product includes software developed by the OpenSSL Project
  22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  23  *
  24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  25  *    endorse or promote products derived from this software without
  26  *    prior written permission. For written permission, please contact
  27  *    licensing@OpenSSL.org.
  28  *
  29  * 5. Products derived from this software may not be called "OpenSSL"
  30  *    nor may "OpenSSL" appear in their names without prior written
  31  *    permission of the OpenSSL Project.
  32  *
  33  * 6. Redistributions of any form whatsoever must retain the following
  34  *    acknowledgment:
  35  *    "This product includes software developed by the OpenSSL Project
  36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  37  *
  38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  49  * OF THE POSSIBILITY OF SUCH DAMAGE.
  50  * ====================================================================
  51  *
  52  * This product includes cryptographic software written by Eric Young
  53  * (eay@cryptsoft.com).  This product includes software written by Tim
  54  * Hudson (tjh@cryptsoft.com).
  55  *
  56  */
  57 
  58 #include <stdio.h>
  59 #include "cryptlib.h"
  60 #include <openssl/evp.h>
  61 #include "asn1_locl.h"
  62 
  63 #define HMAC_TEST_PRIVATE_KEY_FORMAT
  64 
  65 /* HMAC "ASN1" method. This is just here to indicate the
  66  * maximum HMAC output length and to free up an HMAC
  67  * key.
  68  */
  69 
  70 static int hmac_size(const EVP_PKEY *pkey)
  71         {
  72         return EVP_MAX_MD_SIZE;
  73         }
  74 
  75 static void hmac_key_free(EVP_PKEY *pkey)
  76         {
  77         ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
  78         if (os)
  79                 {
  80                 if (os->data)
  81                         OPENSSL_cleanse(os->data, os->length);
  82                 ASN1_OCTET_STRING_free(os);
  83                 }
  84         }
  85 
  86 
  87 static int hmac_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
  88         {
  89         switch (op)
  90                 {
  91                 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
  92                 *(int *)arg2 = NID_sha1;
  93                 return 1;
  94 
  95                 default:
  96                 return -2;
  97                 }
  98         }
  99 
 100 #ifdef HMAC_TEST_PRIVATE_KEY_FORMAT
 101 /* A bogus private key format for test purposes. This is simply the
 102  * HMAC key with "HMAC PRIVATE KEY" in the headers. When enabled the
 103  * genpkey utility can be used to "generate" HMAC keys.
 104  */
 105 
 106 static int old_hmac_decode(EVP_PKEY *pkey,
 107                                         const unsigned char **pder, int derlen)
 108         {
 109         ASN1_OCTET_STRING *os;
 110         os = ASN1_OCTET_STRING_new();
 111         if (!os || !ASN1_OCTET_STRING_set(os, *pder, derlen))
 112                 return 0;
 113         EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, os);
 114         return 1;
 115         }
 116 
 117 static int old_hmac_encode(const EVP_PKEY *pkey, unsigned char **pder)
 118         {
 119         int inc;
 120         ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
 121         if (pder)
 122                 {
 123                 if (!*pder)
 124                         {
 125                         *pder = OPENSSL_malloc(os->length);
 126                         inc = 0;
 127                         }
 128                 else inc = 1;
 129 
 130                 memcpy(*pder, os->data, os->length);
 131 
 132                 if (inc)
 133                         *pder += os->length;
 134                 }
 135 
 136         return os->length;
 137         }
 138 
 139 #endif
 140 
 141 const EVP_PKEY_ASN1_METHOD hmac_asn1_meth =
 142         {
 143         EVP_PKEY_HMAC,
 144         EVP_PKEY_HMAC,
 145         0,
 146 
 147         "HMAC",
 148         "OpenSSL HMAC method",
 149 
 150         0,0,0,0,
 151 
 152         0,0,0,
 153 
 154         hmac_size,
 155         0,
 156         0,0,0,0,0,0,0,
 157 
 158         hmac_key_free,
 159         hmac_pkey_ctrl,
 160 #ifdef HMAC_TEST_PRIVATE_KEY_FORMAT
 161         old_hmac_decode,
 162         old_hmac_encode
 163 #else
 164         0,0
 165 #endif
 166         };