~stepankk/pyopenssl/bug-845445

« back to all changes in this revision

Viewing changes to OpenSSL/crypto/crypto.c

Fix exception propagation and some error handling related to the privatekey passphrase callback.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
 
46
46
    func = (PyObject *)cb_arg;
47
47
    argv = Py_BuildValue("(i)", rwflag);
 
48
    if (argv == NULL) {
 
49
        return 0;
 
50
    }
48
51
    ret = PyEval_CallObject(func, argv);
49
52
    Py_DECREF(argv);
50
 
    if (ret == NULL)
 
53
    if (ret == NULL) {
51
54
        return 0;
52
 
    if (!PyBytes_Check(ret))
53
 
    {
 
55
    }
 
56
    if (!PyBytes_Check(ret)) {
 
57
        Py_DECREF(ret);
54
58
        PyErr_SetString(PyExc_ValueError, "String expected");
55
59
        return 0;
56
60
    }
57
61
    nchars = PyBytes_Size(ret);
58
 
    if (nchars > len)
59
 
        nchars = len;
 
62
    if (nchars > len) {
 
63
        Py_DECREF(ret);
 
64
        PyErr_SetString(PyExc_ValueError,
 
65
                        "passphrase returned by callback is too long");
 
66
        return 0;
 
67
    }
60
68
    strncpy(buf, PyBytes_AsString(ret), nchars);
 
69
    Py_DECREF(ret);
61
70
    return nchars;
62
71
}
63
72
 
 
73
static PyObject *
 
74
raise_current_error(void)
 
75
{
 
76
    if (PyErr_Occurred()) {
 
77
        /*
 
78
         * The python exception from callback is more informative than
 
79
         * OpenSSL's error.
 
80
         */
 
81
        flush_error_queue();
 
82
        return NULL;
 
83
    }
 
84
    exception_from_error_queue(crypto_Error);
 
85
    return NULL;
 
86
}
 
87
 
 
88
static int
 
89
setup_callback(int type, PyObject *pw, pem_password_cb **cb, void **cb_arg) {
 
90
    if (pw == NULL) {
 
91
        *cb = NULL;
 
92
        *cb_arg = NULL;
 
93
        return 1;
 
94
    }
 
95
    if (type != X509_FILETYPE_PEM) {
 
96
        PyErr_SetString(PyExc_ValueError,
 
97
                        "only FILETYPE_PEM key format supports encryption");
 
98
        return 0;
 
99
    }
 
100
    if (PyBytes_Check(pw)) {
 
101
        *cb = NULL;
 
102
        *cb_arg = PyBytes_AsString(pw);
 
103
    } else if (PyCallable_Check(pw)) {
 
104
        *cb = global_passphrase_callback;
 
105
        *cb_arg = pw;
 
106
    } else {
 
107
        PyErr_SetString(PyExc_TypeError,
 
108
                        "Last argument must be string or callable");
 
109
        return 0;
 
110
    }
 
111
    return 1;
 
112
}
 
113
 
64
114
static char crypto_load_privatekey_doc[] = "\n\
65
115
Load a private key from a buffer\n\
66
116
\n\
85
135
    BIO *bio;
86
136
    EVP_PKEY *pkey;
87
137
 
88
 
    if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
89
 
        return NULL;
90
 
 
91
 
    if (pw != NULL)
92
 
    {
93
 
        if (PyBytes_Check(pw))
94
 
        {
95
 
            cb = NULL;
96
 
            cb_arg = PyBytes_AsString(pw);
97
 
        }
98
 
        else if (PyCallable_Check(pw))
99
 
        {
100
 
            cb = global_passphrase_callback;
101
 
            cb_arg = pw;
102
 
        }
103
 
        else
104
 
        {
105
 
            PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
106
 
            return NULL;
107
 
        }
 
138
    if (!PyArg_ParseTuple(args, "is#|O:load_privatekey",
 
139
                          &type, &buffer, &len, &pw)) {
 
140
        return NULL;
 
141
    }
 
142
    if (!setup_callback(type, pw, &cb, &cb_arg)) {
 
143
        return NULL;
108
144
    }
109
145
 
110
146
    bio = BIO_new_mem_buf(buffer, len);
111
 
    switch (type)
112
 
    {
 
147
    if (bio == NULL) {
 
148
        exception_from_error_queue(crypto_Error);
 
149
        return NULL;
 
150
    }
 
151
    switch (type) {
113
152
        case X509_FILETYPE_PEM:
114
153
            pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
115
154
            break;
125
164
    }
126
165
    BIO_free(bio);
127
166
 
128
 
    if (pkey == NULL)
129
 
    {
130
 
        exception_from_error_queue(crypto_Error);
131
 
        return NULL;
 
167
    if (pkey == NULL) {
 
168
        return raise_current_error();
132
169
    }
133
170
 
134
171
    return (PyObject *)crypto_PKey_New(pkey, 1);
164
201
    crypto_PKeyObj *pkey;
165
202
 
166
203
    if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
167
 
                          &crypto_PKey_Type, &pkey, &cipher_name, &pw))
 
204
                          &crypto_PKey_Type, &pkey, &cipher_name, &pw)) {
168
205
        return NULL;
169
 
 
170
 
    if (cipher_name != NULL && pw == NULL)
171
 
    {
 
206
    }
 
207
    if (cipher_name != NULL && pw == NULL) {
172
208
        PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
173
209
        return NULL;
174
210
    }
175
 
    if (cipher_name != NULL)
176
 
    {
 
211
    if (cipher_name != NULL) {
177
212
        cipher = EVP_get_cipherbyname(cipher_name);
178
 
        if (cipher == NULL)
179
 
        {
 
213
        if (cipher == NULL) {
180
214
            PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
181
215
            return NULL;
182
216
        }
183
 
        if (PyBytes_Check(pw))
184
 
        {
185
 
            cb = NULL;
186
 
            cb_arg = PyBytes_AsString(pw);
187
 
        }
188
 
        else if (PyCallable_Check(pw))
189
 
        {
190
 
            cb = global_passphrase_callback;
191
 
            cb_arg = pw;
192
 
        }
193
 
        else
194
 
        {
195
 
            PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
 
217
        if (!setup_callback(type, pw, &cb, &cb_arg)) {
196
218
            return NULL;
197
219
        }
198
220
    }
199
221
 
200
222
    bio = BIO_new(BIO_s_mem());
201
 
    switch (type)
202
 
    {
 
223
    if (bio == NULL) {
 
224
        exception_from_error_queue(crypto_Error);
 
225
        return NULL;
 
226
    }
 
227
    switch (type) {
203
228
        case X509_FILETYPE_PEM:
204
229
            ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
205
 
            if (PyErr_Occurred())
206
 
            {
207
 
                BIO_free(bio);
208
 
                return NULL;
209
 
            }
210
230
            break;
211
231
 
212
232
        case X509_FILETYPE_ASN1:
215
235
 
216
236
        case X509_FILETYPE_TEXT:
217
237
            rsa = EVP_PKEY_get1_RSA(pkey->pkey);
 
238
            if (rsa == NULL) {
 
239
                ret = 0;
 
240
                break;
 
241
            }
218
242
            ret = RSA_print(bio, rsa, 0);
219
 
            RSA_free(rsa); 
 
243
            RSA_free(rsa);
220
244
            break;
221
245
 
222
246
        default:
225
249
            return NULL;
226
250
    }
227
251
 
228
 
    if (ret == 0)
229
 
    {
 
252
    if (ret == 0) {
230
253
        BIO_free(bio);
231
 
        exception_from_error_queue(crypto_Error);
232
 
        return NULL;
 
254
        return raise_current_error();
233
255
    }
234
256
 
235
257
    buf_len = BIO_get_mem_data(bio, &temp);
509
531
    if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
510
532
        return NULL;
511
533
 
512
 
    /* 
513
 
     * Try to read the pkcs7 data from the bio 
 
534
    /*
 
535
     * Try to read the pkcs7 data from the bio
514
536
     */
515
537
    bio = BIO_new_mem_buf(buffer, len);
516
538
    switch (type)