1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
8 * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
9 *
10 * Export of this software from the United States of America may
11 *   require a specific license from the United States Government.
12 *   It is the responsibility of any person or organization contemplating
13 *   export to obtain such a license before exporting.
14 *
15 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
16 * distribute this software and its documentation for any purpose and
17 * without fee is hereby granted, provided that the above copyright
18 * notice appear in all copies and that both that copyright notice and
19 * this permission notice appear in supporting documentation, and that
20 * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
21 * in advertising or publicity pertaining to distribution of the software
22 * without specific, written prior permission.  Richard P. Basch,
23 * Lehman Brothers and M.I.T. make no representations about the suitability
24 * of this software for any purpose.  It is provided "as is" without
25 * express or implied warranty.
26 */
27
28#include "des_int.h"
29
30/*
31 * Triple-DES CBC encryption mode.
32 */
33#ifndef _KERNEL
34int
35mit_des3_cbc_encrypt(krb5_context context, const mit_des_cblock *in, mit_des_cblock *out,
36		     unsigned long length, krb5_keyblock *key,
37		     const mit_des_cblock ivec, int encrypt)
38{
39    int ret = KRB5_PROG_ETYPE_NOSUPP;
40    KRB5_MECH_TO_PKCS algos;
41    CK_MECHANISM mechanism;
42    CK_RV rv;
43    /* For the Key Object */
44    ret = 0;
45
46    if ((rv = get_algo(key->enctype, &algos)) != CKR_OK) {
47        KRB5_LOG0(KRB5_ERR, "failure to get algo id in function "
48            "mit_des3_cbc_encrypt.");
49        ret = PKCS_ERR;
50        goto cleanup;
51    }
52
53    rv = init_key_uef(krb_ctx_hSession(context), key);
54    if (rv != CKR_OK) {
55        KRB5_LOG(KRB5_ERR, "init_key_uef failed in "
56            "mit_des3_cbc_encrypt: rv = 0x%0x", rv);
57        ret = PKCS_ERR;
58        goto cleanup;
59    }
60
61    mechanism.mechanism = algos.enc_algo;
62    mechanism.pParameter = (void*)ivec;
63    if (ivec != NULL)
64    	mechanism.ulParameterLen = sizeof(mit_des_cblock);
65    else
66	mechanism.ulParameterLen = 0;
67
68    if (encrypt)
69        rv = C_EncryptInit(krb_ctx_hSession(context), &mechanism, key->hKey);
70    else
71        rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism, key->hKey);
72
73    if (rv != CKR_OK) {
74        KRB5_LOG(KRB5_ERR, "C_EncryptInit/C_DecryptInit failed in "
75		"mit_des3_cbc_encrypt: rv = 0x%x", rv);
76        ret = PKCS_ERR;
77        goto cleanup;
78    }
79
80    if (encrypt)
81        rv = C_Encrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)in,
82            (CK_ULONG)length, (CK_BYTE_PTR)out,
83            (CK_ULONG_PTR)&length);
84    else
85        rv = C_Decrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)in,
86            (CK_ULONG)length, (CK_BYTE_PTR)out,
87            (CK_ULONG_PTR)&length);
88
89    if (rv != CKR_OK) {
90            KRB5_LOG(KRB5_ERR,
91                "C_Encrypt/C_Decrypt failed in mit_des3_cbc_encrypt: "
92                "rv = 0x%x", rv);
93            ret = PKCS_ERR;
94    }
95cleanup:
96
97final_cleanup:
98    if (ret)
99        (void) memset(out, 0, length);
100
101    KRB5_LOG(KRB5_INFO, "mit_des3_cbc_encrypt() end ret=%d\n", ret);
102    return(ret);
103}
104
105#else
106#include <sys/crypto/api.h>
107
108/* ARGSUSED */
109int
110mit_des3_cbc_encrypt(krb5_context context,
111	const mit_des_cblock *in,
112	mit_des_cblock *out,
113        unsigned long length, krb5_keyblock *key,
114        const mit_des_cblock ivec, int encrypt)
115{
116	int ret = KRB5_PROG_ETYPE_NOSUPP;
117	krb5_data ivdata;
118
119        KRB5_LOG(KRB5_INFO, "mit_des3_cbc_encrypt() start encrypt=%d", encrypt);
120
121	ivdata.data = (char *)ivec;
122	ivdata.length = sizeof(mit_des_cblock);
123
124        ret = k5_ef_crypto((const char *)in, (char *)out,
125			length, key, &ivdata, encrypt);
126
127        KRB5_LOG(KRB5_INFO, "mit_des3_cbc_encrypt() end retval=%d", ret);
128        return(ret);
129}
130#endif /* !_KERNEL */
131