~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to ext/openssl/ossl_pkey.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * $Id: ossl_pkey.c 27440 2010-04-22 08:21:01Z nobu $
 
2
 * $Id: ossl_pkey.c 33317 2011-09-23 05:17:47Z emboss $
3
3
 * 'OpenSSL for Ruby' project
4
4
 * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
5
5
 * All rights reserved.
85
85
    return ossl_pkey_new(pkey);
86
86
}
87
87
 
 
88
/*
 
89
 *  call-seq:
 
90
 *     OpenSSL::PKey.read(string [, pwd ] ) -> PKey
 
91
 *     OpenSSL::PKey.read(file [, pwd ]) -> PKey
 
92
 *
 
93
 * === Parameters
 
94
 * * +string+ is a DER- or PEM-encoded string containing an arbitrary private
 
95
 * or public key.
 
96
 * * +file+ is an instance of +File+ containing a DER- or PEM-encoded
 
97
 * arbitrary private or public key.
 
98
 * * +pwd+ is an optional password in case +string+ or +file+ is an encrypted
 
99
 * PEM resource.
 
100
 */
 
101
static VALUE
 
102
ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
 
103
{
 
104
     EVP_PKEY *pkey;
 
105
     BIO *bio;
 
106
     VALUE data, pass;
 
107
     char *passwd = NULL;
 
108
 
 
109
     rb_scan_args(argc, argv, "11", &data, &pass);
 
110
 
 
111
     bio = ossl_obj2bio(data);
 
112
     if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
 
113
        OSSL_BIO_reset(bio);
 
114
        if (!NIL_P(pass)) {
 
115
            passwd = StringValuePtr(pass);
 
116
        }
 
117
        if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) {
 
118
            OSSL_BIO_reset(bio);
 
119
            if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
 
120
                OSSL_BIO_reset(bio);
 
121
                if (!NIL_P(pass)) {
 
122
                    passwd = StringValuePtr(pass);
 
123
                }
 
124
                pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd);
 
125
            }
 
126
        }
 
127
    }
 
128
 
 
129
    BIO_free(bio);
 
130
    if (!pkey)
 
131
        ossl_raise(rb_eArgError, "Could not parse PKey");
 
132
    return ossl_pkey_new(pkey);
 
133
}
 
134
 
88
135
EVP_PKEY *
89
136
GetPKeyPtr(VALUE obj)
90
137
{
150
197
    return obj;
151
198
}
152
199
 
 
200
/*
 
201
 *  call-seq:
 
202
 *      PKeyClass.new -> self
 
203
 *
 
204
 * Because PKey is an abstract class, actually calling this method explicitly
 
205
 * will raise a +NotImplementedError+.
 
206
 */
153
207
static VALUE
154
208
ossl_pkey_initialize(VALUE self)
155
209
{
159
213
    return self;
160
214
}
161
215
 
 
216
/*
 
217
 *  call-seq:
 
218
 *      pkey.sign(digest, data) -> String
 
219
 *
 
220
 * To sign the +String+ +data+, +digest+, an instance of OpenSSL::Digest, must
 
221
 * be provided. The return value is again a +String+ containing the signature.
 
222
 * A PKeyError is raised should errors occur.
 
223
 * Any previous state of the +Digest+ instance is irrelevant to the signature
 
224
 * outcome, the digest instance is reset to its initial state during the
 
225
 * operation.
 
226
 *
 
227
 * == Example
 
228
 *   data = 'Sign me!'
 
229
 *   digest = OpenSSL::Digest::SHA256.new
 
230
 *   pkey = OpenSSL::PKey::RSA.new(2048)
 
231
 *   signature = pkey.sign(digest, data)
 
232
 */
162
233
static VALUE
163
234
ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
164
235
{
183
254
    return str;
184
255
}
185
256
 
 
257
/*
 
258
 *  call-seq:
 
259
 *      pkey.verify(digest, signature, data) -> String
 
260
 *
 
261
 * To verify the +String+ +signature+, +digest+, an instance of
 
262
 * OpenSSL::Digest, must be provided to re-compute the message digest of the
 
263
 * original +data+, also a +String+. The return value is +true+ if the
 
264
 * signature is valid, +false+ otherwise. A PKeyError is raised should errors
 
265
 * occur.
 
266
 * Any previous state of the +Digest+ instance is irrelevant to the validation
 
267
 * outcome, the digest instance is reset to its initial state during the
 
268
 * operation.
 
269
 *
 
270
 * == Example
 
271
 *   data = 'Sign me!'
 
272
 *   digest = OpenSSL::Digest::SHA256.new
 
273
 *   pkey = OpenSSL::PKey::RSA.new(2048)
 
274
 *   signature = pkey.sign(digest, data)
 
275
 *   pub_key = pkey.public_key
 
276
 *   puts pub_key.verify(digest, signature, data) # => true
 
277
 */
186
278
static VALUE
187
279
ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
188
280
{
194
286
    StringValue(sig);
195
287
    StringValue(data);
196
288
    EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
197
 
    switch (EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LEN(sig), pkey)) {
 
289
    switch (EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey)) {
198
290
    case 0:
199
291
        return Qfalse;
200
292
    case 1:
211
303
void
212
304
Init_ossl_pkey()
213
305
{
214
 
#if 0 /* let rdoc know about mOSSL */
215
 
    mOSSL = rb_define_module("OpenSSL");
 
306
#if 0
 
307
    mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
216
308
#endif
217
309
 
 
310
    /* Document-module: OpenSSL::PKey
 
311
     *
 
312
     * == Asymmetric Public Key Algorithms
 
313
     *
 
314
     * Asymmetric public key algorithms solve the problem of establishing and
 
315
     * sharing secret keys to en-/decrypt messages. The key in such an
 
316
     * algorithm consists of two parts: a public key that may be distributed
 
317
     * to others and a private key that needs to remain secret.
 
318
     *
 
319
     * Messages encrypted with a public key can only be encrypted by
 
320
     * recipients that are in possession of the associated private key.
 
321
     * Since public key algorithms are considerably slower than symmetric
 
322
     * key algorithms (cf. OpenSSL::Cipher) they are often used to establish
 
323
     * a symmetric key shared between two parties that are in possession of
 
324
     * each other's public key.
 
325
     *
 
326
     * Asymmetric algorithms offer a lot of nice features that are used in a
 
327
     * lot of different areas. A very common application is the creation and
 
328
     * validation of digital signatures. To sign a document, the signatory
 
329
     * generally uses a message digest algorithm (cf. OpenSSL::Digest) to
 
330
     * compute a digest of the document that is then encrypted (i.e. signed)
 
331
     * using the private key. Anyone in possession of the public key may then
 
332
     * verify the signature by computing the message digest of the original
 
333
     * document on their own, decrypting the signature using the signatory's
 
334
     * public key and comparing the result to the message digest they
 
335
     * previously computed. The signature is valid if and only if the
 
336
     * decrypted signature is equal to this message digest.
 
337
     *
 
338
     * The PKey module offers support for three popular public/private key
 
339
     * algorithms:
 
340
     * * RSA (OpenSSL::PKey::RSA)
 
341
     * * DSA (OpenSSL::PKey::DSA)
 
342
     * * Elliptic Curve Cryptography (OpenSSL::PKey::EC)
 
343
     * Each of these implementations is in fact a sub-class of the abstract
 
344
     * PKey class which offers the interface for supporting digital signatures
 
345
     * in the form of PKey#sign and PKey#verify.
 
346
     *
 
347
     * == Diffie-Hellman Key Exchange
 
348
     *
 
349
     * Finally PKey also features OpenSSL::PKey::DH, an implementation of
 
350
     * the Diffie-Hellman key exchange protocol based on discrete logarithms
 
351
     * in finite fields, the same basis that DSA is built on.
 
352
     * The Diffie-Hellman protocol can be used to exchange (symmetric) keys
 
353
     * over insecure channels without needing any prior joint knowledge
 
354
     * between the participating parties. As the security of DH demands
 
355
     * relatively long "public keys" (i.e. the part that is overtly
 
356
     * transmitted between participants) DH tends to be quite slow. If
 
357
     * security or speed is your primary concern, OpenSSL::PKey::EC offers
 
358
     * another implementation of the Diffie-Hellman protocol.
 
359
     *
 
360
     */
218
361
    mPKey = rb_define_module_under(mOSSL, "PKey");
219
362
 
 
363
    /* Document-class: OpenSSL::PKey::PKeyError
 
364
     *
 
365
     *Raised when errors occur during PKey#sign or PKey#verify.
 
366
     */
220
367
    ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
221
368
 
 
369
    /* Document-class: OpenSSL::PKey::PKey
 
370
     *
 
371
     * An abstract class that bundles signature creation (PKey#sign) and
 
372
     * validation (PKey#verify) that is common to all implementations except
 
373
     * OpenSSL::PKey::DH
 
374
     * * OpenSSL::PKey::RSA
 
375
     * * OpenSSL::PKey::DSA
 
376
     * * OpenSSL::PKey::EC
 
377
     */
222
378
    cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
223
379
 
 
380
    rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
 
381
 
224
382
    rb_define_alloc_func(cPKey, ossl_pkey_alloc);
225
383
    rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
226
384