xref: /freebsd/crypto/krb5/src/lib/kdb/decrypt_key.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/kdb/decrypt_key.c */
3 /*
4  * Copyright 1990,1991,2023 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  * Copyright (C) 1998 by the FundsXpress, INC.
28  *
29  * All rights reserved.
30  *
31  * Export of this software from the United States of America may require
32  * a specific license from the United States Government.  It is the
33  * responsibility of any person or organization contemplating export to
34  * obtain such a license before exporting.
35  *
36  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
37  * distribute this software and its documentation for any purpose and
38  * without fee is hereby granted, provided that the above copyright
39  * notice appear in all copies and that both that copyright notice and
40  * this permission notice appear in supporting documentation, and that
41  * the name of FundsXpress. not be used in advertising or publicity pertaining
42  * to distribution of the software without specific, written prior
43  * permission.  FundsXpress makes no representations about the suitability of
44  * this software for any purpose.  It is provided "as is" without express
45  * or implied warranty.
46  *
47  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50  */
51 
52 #include "k5-int.h"
53 #include "kdb.h"
54 
55 /* Decrypt key_data, putting the result into dbkey_out and (if not null)
56  * keysalt_out. */
57 krb5_error_code
krb5_dbe_def_decrypt_key_data(krb5_context context,const krb5_keyblock * mkey,const krb5_key_data * kd,krb5_keyblock * dbkey_out,krb5_keysalt * keysalt_out)58 krb5_dbe_def_decrypt_key_data(krb5_context context, const krb5_keyblock *mkey,
59                               const krb5_key_data *kd,
60                               krb5_keyblock *dbkey_out,
61                               krb5_keysalt *keysalt_out)
62 {
63     krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
64     int16_t keylen;
65     krb5_enc_data cipher;
66     krb5_data plain = empty_data();
67     krb5_keyblock kb = { 0 };
68     krb5_keysalt salt = { 0 };
69 
70     memset(dbkey_out, 0, sizeof(*dbkey_out));
71     if (keysalt_out != NULL)
72         memset(keysalt_out, 0, sizeof(*keysalt_out));
73 
74     if (mkey == NULL)
75         return KRB5_KDB_BADSTORED_MKEY;
76 
77     if (kd->key_data_contents[0] == NULL || kd->key_data_length[0] < 2)
78         return KRB5_KDB_INVALIDKEYSIZE;
79 
80     keylen = load_16_le(kd->key_data_contents[0]);
81     if (keylen < 0)
82         return KRB5_KDB_INVALIDKEYSIZE;
83 
84     cipher.enctype = ENCTYPE_UNKNOWN;
85     cipher.ciphertext = make_data(kd->key_data_contents[0] + 2,
86                                   kd->key_data_length[0] - 2);
87     ret = alloc_data(&plain, kd->key_data_length[0] - 2);
88     if (ret)
89         goto cleanup;
90 
91     ret = krb5_c_decrypt(context, mkey, 0, 0, &cipher, &plain);
92     if (ret)
93         goto cleanup;
94 
95     /* Make sure the plaintext has at least as many bytes as the true key
96      * length (it may have more due to padding). */
97     if ((unsigned int)keylen > plain.length) {
98         ret = KRB5_CRYPTO_INTERNAL;
99         if (ret)
100             goto cleanup;
101     }
102 
103     kb.magic = KV5M_KEYBLOCK;
104     kb.enctype = kd->key_data_type[0];
105     kb.length = keylen;
106     kb.contents = (uint8_t *)plain.data;
107     plain = empty_data();
108 
109     /* Decode salt data. */
110     if (keysalt_out != NULL) {
111         if (kd->key_data_ver == 2) {
112             salt.type = kd->key_data_type[1];
113             salt.data.length = kd->key_data_length[1];
114             if (kd->key_data_length[1] > 0) {
115                 ret = alloc_data(&salt.data, kd->key_data_length[1]);
116                 if (ret)
117                     goto cleanup;
118                 memcpy(salt.data.data, kd->key_data_contents[1],
119                        salt.data.length);
120             }
121         } else {
122             salt.type = KRB5_KDB_SALTTYPE_NORMAL;
123         }
124     }
125 
126     *dbkey_out = kb;
127     if (keysalt_out != NULL)
128         *keysalt_out = salt;
129     memset(&kb, 0, sizeof(kb));
130     memset(&salt, 0, sizeof(salt));
131 
132 cleanup:
133     zapfree(plain.data, plain.length);
134     krb5_free_keyblock_contents(context, &kb);
135     free(salt.data.data);
136     return ret;
137 }
138