components/krb5/Solaris/ucrypto/enc_provider/des.c
changeset 7950 50d75ee82dad
equal deleted inserted replaced
7949:e94c44902e51 7950:50d75ee82dad
       
     1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
       
     2 /* lib/crypto/openssl/enc_provider/des.c */
       
     3 /*
       
     4  * Copyright (C) 2009 by the Massachusetts Institute of Technology.
       
     5  * All rights reserved.
       
     6  *
       
     7  * Export of this software from the United States of America may
       
     8  *   require a specific license from the United States Government.
       
     9  *   It is the responsibility of any person or organization contemplating
       
    10  *   export to obtain such a license before exporting.
       
    11  *
       
    12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
       
    13  * distribute this software and its documentation for any purpose and
       
    14  * without fee is hereby granted, provided that the above copyright
       
    15  * notice appear in all copies and that both that copyright notice and
       
    16  * this permission notice appear in supporting documentation, and that
       
    17  * the name of M.I.T. not be used in advertising or publicity pertaining
       
    18  * to distribution of the software without specific, written prior
       
    19  * permission.  Furthermore if you modify this software you must label
       
    20  * your software as modified software and not distribute it in such a
       
    21  * fashion that it might be confused with the original M.I.T. software.
       
    22  * M.I.T. makes no representations about the suitability of
       
    23  * this software for any purpose.  It is provided "as is" without express
       
    24  * or implied warranty.
       
    25  */
       
    26 
       
    27 /*
       
    28  * Copyright (C) 1998 by the FundsXpress, INC.
       
    29  *
       
    30  * All rights reserved.
       
    31  *
       
    32  * Export of this software from the United States of America may require
       
    33  * a specific license from the United States Government.  It is the
       
    34  * responsibility of any person or organization contemplating export to
       
    35  * obtain such a license before exporting.
       
    36  *
       
    37  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
       
    38  * distribute this software and its documentation for any purpose and
       
    39  * without fee is hereby granted, provided that the above copyright
       
    40  * notice appear in all copies and that both that copyright notice and
       
    41  * this permission notice appear in supporting documentation, and that
       
    42  * the name of FundsXpress. not be used in advertising or publicity pertaining
       
    43  * to distribution of the software without specific, written prior
       
    44  * permission.  FundsXpress makes no representations about the suitability of
       
    45  * this software for any purpose.  It is provided "as is" without express
       
    46  * or implied warranty.
       
    47  *
       
    48  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
       
    49  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
       
    50  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
       
    51  */
       
    52 /*
       
    53  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
       
    54  */
       
    55 
       
    56 #include "crypto_int.h"
       
    57 #include <libucrypto.h>
       
    58 
       
    59 #define DES_BLOCK_SIZE 8
       
    60 #define DES_KEY_SIZE 8
       
    61 #define DES_KEY_BYTES 7
       
    62 
       
    63 static krb5_error_code
       
    64 validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data,
       
    65          size_t num_data, size_t *inlen)
       
    66 {
       
    67     size_t input_length = iov_total_length(data, num_data, FALSE);
       
    68 
       
    69     if (key->keyblock.length != DES_KEY_SIZE)
       
    70         return KRB5_BAD_KEYSIZE;
       
    71     if ((input_length % DES_BLOCK_SIZE) != 0)
       
    72         return KRB5_BAD_MSIZE;
       
    73     if (ivec && (ivec->length != DES_BLOCK_SIZE))
       
    74         return KRB5_BAD_MSIZE;
       
    75 
       
    76     if (inlen != NULL)
       
    77         *inlen = input_length;
       
    78 
       
    79     return 0;
       
    80 }
       
    81 
       
    82 static krb5_error_code
       
    83 k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
       
    84                size_t num_data)
       
    85 {
       
    86     int ret;
       
    87     size_t  olen, dlen;
       
    88     uchar_t *obuf, *dbuf;
       
    89     uchar_t tmp_iv[DES_BLOCK_SIZE];
       
    90     struct iov_cursor cursor;
       
    91 
       
    92     ret = validate(key, ivec, data, num_data, &dlen);
       
    93     if (ret != 0 || dlen == 0)
       
    94         return ret;
       
    95 
       
    96     if (ivec && ivec->data)
       
    97         memcpy(tmp_iv, ivec->data, ivec->length);
       
    98     else
       
    99         memset(tmp_iv, 0, sizeof(tmp_iv));
       
   100 
       
   101     olen = dlen;
       
   102     obuf = malloc(olen);
       
   103     if (!obuf)
       
   104         return ENOMEM;
       
   105 
       
   106     dbuf = malloc(dlen);
       
   107     if (!dbuf){
       
   108         free(obuf);
       
   109         return ENOMEM;
       
   110     }
       
   111 
       
   112     /* Init iov cursor to gather data for encypting (FALSE) */
       
   113     k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
       
   114     /* Get all that data into dbuf */
       
   115     k5_iov_cursor_get(&cursor, dbuf);
       
   116 
       
   117     if (ucrypto_encrypt(CRYPTO_DES_CBC,
       
   118                         key->keyblock.contents,
       
   119                         key->keyblock.length,
       
   120                         tmp_iv, sizeof(tmp_iv),
       
   121                         dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
       
   122         ret = KRB5_CRYPTO_INTERNAL;
       
   123     } else {
       
   124         k5_iov_cursor_put(&cursor, obuf);
       
   125     }
       
   126 
       
   127     /*
       
   128      * Updating the ivec arg, if present because of an old/obscure concept of
       
   129      * cipher state that is being used by only BSD rlogin.  See RFCs 1391 and
       
   130      * 1392 in regards to the vague description of cipher state.
       
   131      */
       
   132     if (!ret && ivec && ivec->data) {
       
   133         /* Copy last block of cipher text output */
       
   134         memcpy(ivec->data, obuf + (dlen - DES_BLOCK_SIZE), DES_BLOCK_SIZE);
       
   135     }
       
   136 
       
   137     zapfree(obuf, olen);
       
   138     zapfree(dbuf, dlen);
       
   139 
       
   140     return ret;
       
   141 }
       
   142 
       
   143 static krb5_error_code
       
   144 k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
       
   145                size_t num_data)
       
   146 {
       
   147     int ret;
       
   148     size_t  olen, dlen;
       
   149     uchar_t *obuf, *dbuf;
       
   150     uchar_t tmp_iv[DES_BLOCK_SIZE];
       
   151     struct iov_cursor cursor;
       
   152 
       
   153     ret = validate(key, ivec, data, num_data, &dlen);
       
   154     if (ret != 0 || dlen == 0)
       
   155         return ret;
       
   156 
       
   157     if (ivec && ivec->data)
       
   158         memcpy(tmp_iv, ivec->data, ivec->length);
       
   159     else
       
   160         memset(tmp_iv, 0, sizeof(tmp_iv));
       
   161 
       
   162     olen = dlen;
       
   163     obuf = malloc(olen);
       
   164     if (!obuf)
       
   165         return ENOMEM;
       
   166 
       
   167     dbuf = malloc(dlen);
       
   168     if (!dbuf){
       
   169         free(obuf);
       
   170         return ENOMEM;
       
   171     }
       
   172 
       
   173     /* Init iov cursor to gather cipher text for decrypting (FALSE) */
       
   174     k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
       
   175     /* Gather all that cipher text into dbuf */
       
   176     k5_iov_cursor_get(&cursor, dbuf);
       
   177 
       
   178     if (ucrypto_decrypt(CRYPTO_DES_CBC,
       
   179                         key->keyblock.contents,
       
   180                         key->keyblock.length,
       
   181                         tmp_iv, sizeof(tmp_iv),
       
   182                         dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
       
   183         ret = KRB5_CRYPTO_INTERNAL;
       
   184     } else {
       
   185         k5_iov_cursor_put(&cursor, obuf);
       
   186     }
       
   187 
       
   188     /*
       
   189      * Updating the ivec arg, if present because of an old/obscure concept of
       
   190      * cipher state that is being used by only BSD rlogin.  See RFCs 1391 and
       
   191      * 1392 in regards to the vague description of cipher state.
       
   192      */
       
   193     if (!ret && ivec && ivec->data) {
       
   194         /* Copy last block of cipher text input */
       
   195         memcpy(ivec->data, dbuf + (dlen - DES_BLOCK_SIZE), DES_BLOCK_SIZE);
       
   196     }
       
   197 
       
   198     zapfree(obuf, olen);
       
   199     zapfree(dbuf, dlen);
       
   200 
       
   201     return ret;
       
   202 }
       
   203 
       
   204 static krb5_error_code
       
   205 k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data,
       
   206                const krb5_data *ivec, krb5_data *output)
       
   207 {
       
   208     int ret;
       
   209     struct iov_cursor cursor;
       
   210     uchar_t blockY[DES_BLOCK_SIZE], blockB[DES_BLOCK_SIZE];
       
   211     size_t olen;
       
   212 
       
   213     ret = validate(key, ivec, data, num_data, NULL);
       
   214     if (ret != 0)
       
   215         return ret;
       
   216 
       
   217     if (output->length != DES_BLOCK_SIZE)
       
   218         return KRB5_BAD_MSIZE;
       
   219 
       
   220     if (ivec != NULL)
       
   221         memcpy(blockY, ivec->data, DES_BLOCK_SIZE);
       
   222     else
       
   223         memset(blockY, 0, DES_BLOCK_SIZE);
       
   224 
       
   225     k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE);
       
   226     while (k5_iov_cursor_get(&cursor, blockB)) {
       
   227         store_64_n(load_64_n(blockB) ^ load_64_n(blockY), blockB);
       
   228         olen = sizeof(blockY);
       
   229         if (ucrypto_encrypt(CRYPTO_DES_ECB,
       
   230                             key->keyblock.contents,
       
   231                             key->keyblock.length,
       
   232                             NULL, 0,
       
   233                             blockB, sizeof(blockB),
       
   234                             blockY, &olen) != CRYPTO_SUCCESS) {
       
   235             return KRB5_CRYPTO_INTERNAL;
       
   236         }
       
   237     }
       
   238 
       
   239     memcpy(output->data, blockY, DES_BLOCK_SIZE);
       
   240     return 0;
       
   241 }
       
   242 
       
   243 const struct krb5_enc_provider krb5int_enc_des = {
       
   244     DES_BLOCK_SIZE,
       
   245     DES_KEY_BYTES, DES_KEY_SIZE,
       
   246     k5_des_encrypt,
       
   247     k5_des_decrypt,
       
   248     k5_des_cbc_mac,
       
   249     krb5int_des_init_state,
       
   250     krb5int_default_free_state
       
   251 };