DESERIALIZER: Implement decryption of password protected objects
[openssl.git] / crypto / serializer / serdes_pass.c
1 /*
2  * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <openssl/err.h>
11 #include <openssl/ui.h>
12 #include <openssl/core_names.h>
13 #include "internal/cryptlib.h"
14 #include "serializer_local.h"
15
16 /* Passphrase callbacks for any who need it */
17
18 /*
19  * First, define the generic passphrase function that supports both
20  * outgoing (with passphrase verify) and incoming (without passphrase
21  * verify) passphrase reading.
22  */
23 static int do_passphrase(char *pass, size_t pass_size, size_t *pass_len,
24                          const OSSL_PARAM params[], void *arg, int verify,
25                          const UI_METHOD *ui_method, void *ui_data, int errlib)
26 {
27     const OSSL_PARAM *p;
28     const char *prompt_info = NULL;
29     char *prompt = NULL, *vpass = NULL;
30     int prompt_idx = -1, verify_idx = -1;
31     UI *ui = NULL;
32     int ret = 0;
33
34     if (!ossl_assert(pass != NULL && pass_size != 0 && pass_len != NULL)) {
35         ERR_raise(errlib, ERR_R_PASSED_NULL_PARAMETER);
36         return 0;
37     }
38
39     if ((p = OSSL_PARAM_locate_const(params,
40                                      OSSL_PASSPHRASE_PARAM_INFO)) != NULL) {
41         if (p->data_type != OSSL_PARAM_UTF8_STRING)
42             return 0;
43         prompt_info = p->data;
44     }
45
46     if ((ui = UI_new()) == NULL) {
47         ERR_raise(errlib, ERR_R_MALLOC_FAILURE);
48         return 0;
49     }
50
51     UI_set_method(ui, ui_method);
52     UI_add_user_data(ui, ui_data);
53
54     /* Get an application constructed prompt */
55     prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
56    if (prompt == NULL) {
57         ERR_raise(errlib, ERR_R_MALLOC_FAILURE);
58         goto end;
59     }
60
61     prompt_idx = UI_add_input_string(ui, prompt,
62                                      UI_INPUT_FLAG_DEFAULT_PWD,
63                                      pass, 0, pass_size - 1) - 1;
64     if (prompt_idx < 0) {
65         ERR_raise(errlib, ERR_R_UI_LIB);
66         goto end;
67     }
68
69     if (verify) {
70         /* Get a buffer for verification prompt */
71         vpass = OPENSSL_zalloc(pass_size);
72         if (vpass == NULL) {
73             ERR_raise(errlib, ERR_R_MALLOC_FAILURE);
74             goto end;
75         }
76         verify_idx = UI_add_verify_string(ui, prompt,
77                                           UI_INPUT_FLAG_DEFAULT_PWD,
78                                           vpass, 0, pass_size - 1,
79                                           pass) - 1;
80         if (verify_idx < 0) {
81             ERR_raise(errlib, ERR_R_UI_LIB);
82             goto end;
83         }
84     }
85
86     switch (UI_process(ui)) {
87     case -2:
88         ERR_raise(errlib, ERR_R_INTERRUPTED_OR_CANCELLED);
89         break;
90     case -1:
91         ERR_raise(errlib, ERR_R_UI_LIB);
92         break;
93     default:
94         *pass_len = (size_t)UI_get_result_length(ui, prompt_idx);
95         ret = 1;
96         break;
97     }
98
99  end:
100     OPENSSL_free(vpass);
101     OPENSSL_free(prompt);
102     UI_free(ui);
103     return ret;
104 }
105
106 /*
107  * Serializers typically want to get an outgoing passphrase, while
108  * deserializers typically want to get en incoming passphrase.
109  */
110 int ossl_serializer_passphrase_out_cb(char *pass, size_t pass_size,
111                                       size_t *pass_len,
112                                       const OSSL_PARAM params[], void *arg)
113 {
114     OSSL_SERIALIZER_CTX *ctx = arg;
115
116     if (!ossl_assert(ctx != NULL)) {
117         ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
118         return 0;
119     }
120
121     return do_passphrase(pass, pass_size, pass_len, params, arg, 1,
122                          ctx->ui_method, ctx->ui_data,
123                          ERR_LIB_OSSL_SERIALIZER);
124 }
125
126 int ossl_deserializer_passphrase_in_cb(char *pass, size_t pass_size,
127                                        size_t *pass_len,
128                                        const OSSL_PARAM params[], void *arg)
129 {
130     OSSL_DESERIALIZER_CTX *ctx = arg;
131
132     if (!ossl_assert(ctx != NULL)) {
133         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
134         return 0;
135     }
136
137     if (ctx->cached_passphrase != NULL) {
138         size_t len = ctx->cached_passphrase_len;
139
140         if (len > pass_size)
141             len = pass_size;
142         memcpy(pass, ctx->cached_passphrase, len);
143         *pass_len = len;
144         return 1;
145     } else {
146         if ((ctx->cached_passphrase = OPENSSL_zalloc(pass_size)) == NULL) {
147             ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE);
148             return 0;
149         }
150     }
151     if (do_passphrase(pass, pass_size, pass_len, params, arg, 0,
152                       ctx->ui_method, ctx->ui_data,
153                       ERR_LIB_OSSL_DESERIALIZER)) {
154         memcpy(ctx->cached_passphrase, pass, *pass_len);
155         ctx->cached_passphrase_len = *pass_len;
156         return 1;
157     }
158     return 0;
159 }