Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /* 00002 * $Id: ossl.c 39584 2013-03-04 15:17:27Z nagachika $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> 00005 * All rights reserved. 00006 */ 00007 /* 00008 * This program is licenced under the same licence as Ruby. 00009 * (See the file 'LICENCE'.) 00010 */ 00011 #include "ossl.h" 00012 #include <stdarg.h> /* for ossl_raise */ 00013 00014 /* 00015 * String to HEXString conversion 00016 */ 00017 int 00018 string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len) 00019 { 00020 static const char hex[]="0123456789abcdef"; 00021 int i, len = 2 * buf_len; 00022 00023 if (buf_len < 0 || len < buf_len) { /* PARANOIA? */ 00024 return -1; 00025 } 00026 if (!hexbuf) { /* if no buf, return calculated len */ 00027 if (hexbuf_len) { 00028 *hexbuf_len = len; 00029 } 00030 return len; 00031 } 00032 if (!(*hexbuf = OPENSSL_malloc(len + 1))) { 00033 return -1; 00034 } 00035 for (i = 0; i < buf_len; i++) { 00036 (*hexbuf)[2 * i] = hex[((unsigned char)buf[i]) >> 4]; 00037 (*hexbuf)[2 * i + 1] = hex[buf[i] & 0x0f]; 00038 } 00039 (*hexbuf)[2 * i] = '\0'; 00040 00041 if (hexbuf_len) { 00042 *hexbuf_len = len; 00043 } 00044 return len; 00045 } 00046 00047 /* 00048 * Data Conversion 00049 */ 00050 #define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \ 00051 STACK_OF(type) * \ 00052 ossl_##name##_ary2sk0(VALUE ary) \ 00053 { \ 00054 STACK_OF(type) *sk; \ 00055 VALUE val; \ 00056 type *x; \ 00057 int i; \ 00058 \ 00059 Check_Type(ary, T_ARRAY); \ 00060 sk = sk_##type##_new_null(); \ 00061 if (!sk) ossl_raise(eOSSLError, NULL); \ 00062 \ 00063 for (i = 0; i < RARRAY_LEN(ary); i++) { \ 00064 val = rb_ary_entry(ary, i); \ 00065 if (!rb_obj_is_kind_of(val, expected_class)) { \ 00066 sk_##type##_pop_free(sk, type##_free); \ 00067 ossl_raise(eOSSLError, "object in array not" \ 00068 " of class ##type##"); \ 00069 } \ 00070 x = dup(val); /* NEED TO DUP */ \ 00071 sk_##type##_push(sk, x); \ 00072 } \ 00073 return sk; \ 00074 } \ 00075 \ 00076 STACK_OF(type) * \ 00077 ossl_protect_##name##_ary2sk(VALUE ary, int *status) \ 00078 { \ 00079 return (STACK_OF(type)*)rb_protect( \ 00080 (VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \ 00081 ary, \ 00082 status); \ 00083 } \ 00084 \ 00085 STACK_OF(type) * \ 00086 ossl_##name##_ary2sk(VALUE ary) \ 00087 { \ 00088 STACK_OF(type) *sk; \ 00089 int status = 0; \ 00090 \ 00091 sk = ossl_protect_##name##_ary2sk(ary, &status); \ 00092 if (status) rb_jump_tag(status); \ 00093 \ 00094 return sk; \ 00095 } 00096 OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr) 00097 00098 #define OSSL_IMPL_SK2ARY(name, type) \ 00099 VALUE \ 00100 ossl_##name##_sk2ary(STACK_OF(type) *sk) \ 00101 { \ 00102 type *t; \ 00103 int i, num; \ 00104 VALUE ary; \ 00105 \ 00106 if (!sk) { \ 00107 OSSL_Debug("empty sk!"); \ 00108 return Qnil; \ 00109 } \ 00110 num = sk_##type##_num(sk); \ 00111 if (num < 0) { \ 00112 OSSL_Debug("items in sk < -1???"); \ 00113 return rb_ary_new(); \ 00114 } \ 00115 ary = rb_ary_new2(num); \ 00116 \ 00117 for (i=0; i<num; i++) { \ 00118 t = sk_##type##_value(sk, i); \ 00119 rb_ary_push(ary, ossl_##name##_new(t)); \ 00120 } \ 00121 return ary; \ 00122 } 00123 OSSL_IMPL_SK2ARY(x509, X509) 00124 OSSL_IMPL_SK2ARY(x509crl, X509_CRL) 00125 OSSL_IMPL_SK2ARY(x509name, X509_NAME) 00126 00127 static VALUE 00128 ossl_str_new(int size) 00129 { 00130 return rb_str_new(0, size); 00131 } 00132 00133 VALUE 00134 ossl_buf2str(char *buf, int len) 00135 { 00136 VALUE str; 00137 int status = 0; 00138 00139 str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status); 00140 if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len); 00141 OPENSSL_free(buf); 00142 if(status) rb_jump_tag(status); 00143 00144 return str; 00145 } 00146 00147 /* 00148 * our default PEM callback 00149 */ 00150 static VALUE 00151 ossl_pem_passwd_cb0(VALUE flag) 00152 { 00153 VALUE pass; 00154 00155 pass = rb_yield(flag); 00156 SafeStringValue(pass); 00157 00158 return pass; 00159 } 00160 00161 int 00162 ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd) 00163 { 00164 int len, status = 0; 00165 VALUE rflag, pass; 00166 00167 if (pwd || !rb_block_given_p()) 00168 return PEM_def_callback(buf, max_len, flag, pwd); 00169 00170 while (1) { 00171 /* 00172 * when the flag is nonzero, this passphrase 00173 * will be used to perform encryption; otherwise it will 00174 * be used to perform decryption. 00175 */ 00176 rflag = flag ? Qtrue : Qfalse; 00177 pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status); 00178 if (status) { 00179 /* ignore an exception raised. */ 00180 rb_set_errinfo(Qnil); 00181 return -1; 00182 } 00183 len = RSTRING_LENINT(pass); 00184 if (len < 4) { /* 4 is OpenSSL hardcoded limit */ 00185 rb_warning("password must be longer than 4 bytes"); 00186 continue; 00187 } 00188 if (len > max_len) { 00189 rb_warning("password must be shorter then %d bytes", max_len-1); 00190 continue; 00191 } 00192 memcpy(buf, RSTRING_PTR(pass), len); 00193 break; 00194 } 00195 return len; 00196 } 00197 00198 /* 00199 * Verify callback 00200 */ 00201 int ossl_verify_cb_idx; 00202 00203 VALUE 00204 ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args) 00205 { 00206 return rb_funcall(args->proc, rb_intern("call"), 2, 00207 args->preverify_ok, args->store_ctx); 00208 } 00209 00210 int 00211 ossl_verify_cb(int ok, X509_STORE_CTX *ctx) 00212 { 00213 VALUE proc, rctx, ret; 00214 struct ossl_verify_cb_args args; 00215 int state = 0; 00216 00217 proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx); 00218 if ((void*)proc == 0) 00219 proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx); 00220 if ((void*)proc == 0) 00221 return ok; 00222 if (!NIL_P(proc)) { 00223 ret = Qfalse; 00224 rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, 00225 (VALUE)ctx, &state); 00226 if (state) { 00227 rb_set_errinfo(Qnil); 00228 rb_warn("StoreContext initialization failure"); 00229 } 00230 else { 00231 args.proc = proc; 00232 args.preverify_ok = ok ? Qtrue : Qfalse; 00233 args.store_ctx = rctx; 00234 ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state); 00235 if (state) { 00236 rb_set_errinfo(Qnil); 00237 rb_warn("exception in verify_callback is ignored"); 00238 } 00239 ossl_x509stctx_clear_ptr(rctx); 00240 } 00241 if (ret == Qtrue) { 00242 X509_STORE_CTX_set_error(ctx, X509_V_OK); 00243 ok = 1; 00244 } 00245 else{ 00246 if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) { 00247 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED); 00248 } 00249 ok = 0; 00250 } 00251 } 00252 00253 return ok; 00254 } 00255 00256 /* 00257 * main module 00258 */ 00259 VALUE mOSSL; 00260 00261 /* 00262 * OpenSSLError < StandardError 00263 */ 00264 VALUE eOSSLError; 00265 00266 /* 00267 * Convert to DER string 00268 */ 00269 ID ossl_s_to_der; 00270 00271 VALUE 00272 ossl_to_der(VALUE obj) 00273 { 00274 VALUE tmp; 00275 00276 tmp = rb_funcall(obj, ossl_s_to_der, 0); 00277 StringValue(tmp); 00278 00279 return tmp; 00280 } 00281 00282 VALUE 00283 ossl_to_der_if_possible(VALUE obj) 00284 { 00285 if(rb_respond_to(obj, ossl_s_to_der)) 00286 return ossl_to_der(obj); 00287 return obj; 00288 } 00289 00290 /* 00291 * Errors 00292 */ 00293 static VALUE 00294 ossl_make_error(VALUE exc, const char *fmt, va_list args) 00295 { 00296 char buf[BUFSIZ]; 00297 const char *msg; 00298 long e; 00299 int len = 0; 00300 00301 #ifdef HAVE_ERR_PEEK_LAST_ERROR 00302 e = ERR_peek_last_error(); 00303 #else 00304 e = ERR_peek_error(); 00305 #endif 00306 if (fmt) { 00307 len = vsnprintf(buf, BUFSIZ, fmt, args); 00308 } 00309 if (len < BUFSIZ && e) { 00310 if (dOSSL == Qtrue) /* FULL INFO */ 00311 msg = ERR_error_string(e, NULL); 00312 else 00313 msg = ERR_reason_error_string(e); 00314 len += snprintf(buf+len, BUFSIZ-len, "%s%s", (len ? ": " : ""), msg); 00315 } 00316 if (dOSSL == Qtrue){ /* show all errors on the stack */ 00317 while ((e = ERR_get_error()) != 0){ 00318 rb_warn("error on stack: %s", ERR_error_string(e, NULL)); 00319 } 00320 } 00321 ERR_clear_error(); 00322 00323 if(len > BUFSIZ) len = rb_long2int(strlen(buf)); 00324 return rb_exc_new(exc, buf, len); 00325 } 00326 00327 void 00328 ossl_raise(VALUE exc, const char *fmt, ...) 00329 { 00330 va_list args; 00331 VALUE err; 00332 va_start(args, fmt); 00333 err = ossl_make_error(exc, fmt, args); 00334 va_end(args); 00335 rb_exc_raise(err); 00336 } 00337 00338 VALUE 00339 ossl_exc_new(VALUE exc, const char *fmt, ...) 00340 { 00341 va_list args; 00342 VALUE err; 00343 va_start(args, fmt); 00344 err = ossl_make_error(exc, fmt, args); 00345 va_end(args); 00346 return err; 00347 } 00348 00349 /* 00350 * call-seq: 00351 * OpenSSL.errors -> [String...] 00352 * 00353 * See any remaining errors held in queue. 00354 * 00355 * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation. 00356 */ 00357 VALUE 00358 ossl_get_errors() 00359 { 00360 VALUE ary; 00361 long e; 00362 00363 ary = rb_ary_new(); 00364 while ((e = ERR_get_error()) != 0){ 00365 rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL))); 00366 } 00367 00368 return ary; 00369 } 00370 00371 /* 00372 * Debug 00373 */ 00374 VALUE dOSSL; 00375 00376 #if !defined(HAVE_VA_ARGS_MACRO) 00377 void 00378 ossl_debug(const char *fmt, ...) 00379 { 00380 va_list args; 00381 00382 if (dOSSL == Qtrue) { 00383 fprintf(stderr, "OSSL_DEBUG: "); 00384 va_start(args, fmt); 00385 vfprintf(stderr, fmt, args); 00386 va_end(args); 00387 fprintf(stderr, " [CONTEXT N/A]\n"); 00388 } 00389 } 00390 #endif 00391 00392 /* 00393 * call-seq: 00394 * OpenSSL.debug -> true | false 00395 */ 00396 static VALUE 00397 ossl_debug_get(VALUE self) 00398 { 00399 return dOSSL; 00400 } 00401 00402 /* 00403 * call-seq: 00404 * OpenSSL.debug = boolean -> boolean 00405 * 00406 * Turns on or off CRYPTO_MEM_CHECK. 00407 * Also shows some debugging message on stderr. 00408 */ 00409 static VALUE 00410 ossl_debug_set(VALUE self, VALUE val) 00411 { 00412 VALUE old = dOSSL; 00413 dOSSL = val; 00414 00415 if (old != dOSSL) { 00416 if (dOSSL == Qtrue) { 00417 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 00418 fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n"); 00419 } else if (old == Qtrue) { 00420 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); 00421 fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n"); 00422 } 00423 } 00424 return val; 00425 } 00426 00427 /* 00428 * call-seq: 00429 * OpenSSL.fips_mode = boolean -> boolean 00430 * 00431 * Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an 00432 * effect for FIPS-capable installations of the OpenSSL library. Trying to do 00433 * so otherwise will result in an error. 00434 * 00435 * === Examples 00436 * 00437 * OpenSSL.fips_mode = true # turn FIPS mode on 00438 * OpenSSL.fips_mode = false # and off again 00439 */ 00440 static VALUE 00441 ossl_fips_mode_set(VALUE self, VALUE enabled) 00442 { 00443 00444 #ifdef HAVE_OPENSSL_FIPS 00445 if (RTEST(enabled)) { 00446 int mode = FIPS_mode(); 00447 if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */ 00448 ossl_raise(eOSSLError, "Turning on FIPS mode failed"); 00449 } else { 00450 if(!FIPS_mode_set(0)) /* turning off twice is OK */ 00451 ossl_raise(eOSSLError, "Turning off FIPS mode failed"); 00452 } 00453 return enabled; 00454 #else 00455 if (RTEST(enabled)) 00456 ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode"); 00457 return enabled; 00458 #endif 00459 } 00460 00461 /* 00462 * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the 00463 * OpenSSL[http://www.openssl.org/] library. 00464 * 00465 * = Examples 00466 * 00467 * All examples assume you have loaded OpenSSL with: 00468 * 00469 * require 'openssl' 00470 * 00471 * These examples build atop each other. For example the key created in the 00472 * next is used in throughout these examples. 00473 * 00474 * == Keys 00475 * 00476 * === Creating a Key 00477 * 00478 * This example creates a 2048 bit RSA keypair and writes it to the current 00479 * directory. 00480 * 00481 * key = OpenSSL::PKey::RSA.new 2048 00482 * 00483 * open 'private_key.pem', 'w' do |io| io.write key.to_pem end 00484 * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end 00485 * 00486 * === Exporting a Key 00487 * 00488 * Keys saved to disk without encryption are not secure as anyone who gets 00489 * ahold of the key may use it unless it is encrypted. In order to securely 00490 * export a key you may export it with a pass phrase. 00491 * 00492 * cipher = OpenSSL::Cipher.new 'AES-128-CBC' 00493 * pass_phrase = 'my secure pass phrase goes here' 00494 * 00495 * key_secure = key.export cipher, pass_phrase 00496 * 00497 * open 'private.secure.pem', 'w' do |io| 00498 * io.write key_secure 00499 * end 00500 * 00501 * OpenSSL::Cipher.ciphers returns a list of available ciphers. 00502 * 00503 * === Loading a Key 00504 * 00505 * A key can also be loaded from a file. 00506 * 00507 * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem' 00508 * key2.public? # => true 00509 * 00510 * or 00511 * 00512 * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem' 00513 * key3.private? # => false 00514 * 00515 * === Loading an Encrypted Key 00516 * 00517 * OpenSSL will prompt you for your pass phrase when loading an encrypted key. 00518 * If you will not be able to type in the pass phrase you may provide it when 00519 * loading the key: 00520 * 00521 * key4_pem = File.read 'private.secure.pem' 00522 * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase 00523 * 00524 * == RSA Encryption 00525 * 00526 * RSA provides encryption and decryption using the public and private keys. 00527 * You can use a variety of padding methods depending upon the intended use of 00528 * encrypted data. 00529 * 00530 * === Encryption & Decryption 00531 * 00532 * Asymmetric public/private key encryption is slow and victim to attack in 00533 * cases where it is used without padding or directly to encrypt larger chunks 00534 * of data. Typical use cases for RSA encryption involve "wrapping" a symmetric 00535 * key with the public key of the recipient who would "unwrap" that symmetric 00536 * key again using their private key. 00537 * The following illustrates a simplified example of such a key transport 00538 * scheme. It shouldn't be used in practice, though, standardized protocols 00539 * should always be preferred. 00540 * 00541 * wrapped_key = key.public_encrypt key 00542 * 00543 * A symmetric key encrypted with the public key can only be decrypted with 00544 * the corresponding private key of the recipient. 00545 * 00546 * original_key = key.private_decrypt wrapped_key 00547 * 00548 * By default PKCS#1 padding will be used, but it is also possible to use 00549 * other forms of padding, see PKey::RSA for further details. 00550 * 00551 * === Signatures 00552 * 00553 * Using "private_encrypt" to encrypt some data with the private key is 00554 * equivalent to applying a digital signature to the data. A verifying 00555 * party may validate the signature by comparing the result of decrypting 00556 * the signature with "public_decrypt" to the original data. However, 00557 * OpenSSL::PKey already has methods "sign" and "verify" that handle 00558 * digital signatures in a standardized way - "private_encrypt" and 00559 * "public_decrypt" shouldn't be used in practice. 00560 * 00561 * To sign a document, a cryptographically secure hash of the document is 00562 * computed first, which is then signed using the private key. 00563 * 00564 * digest = OpenSSL::Digest::SHA256.new 00565 * signature = key.sign digest, document 00566 * 00567 * To validate the signature, again a hash of the document is computed and 00568 * the signature is decrypted using the public key. The result is then 00569 * compared to the hash just computed, if they are equal the signature was 00570 * valid. 00571 * 00572 * digest = OpenSSL::Digest::SHA256.new 00573 * if key.verify digest, signature, document 00574 * puts 'Valid' 00575 * else 00576 * puts 'Invalid' 00577 * end 00578 * 00579 * == PBKDF2 Password-based Encryption 00580 * 00581 * If supported by the underlying OpenSSL version used, Password-based 00582 * Encryption should use the features of PKCS5. If not supported or if 00583 * required by legacy applications, the older, less secure methods specified 00584 * in RFC 2898 are also supported (see below). 00585 * 00586 * PKCS5 supports PBKDF2 as it was specified in PKCS#5 00587 * v2.0[http://www.rsa.com/rsalabs/node.asp?id=2127]. It still uses a 00588 * password, a salt, and additionally a number of iterations that will 00589 * slow the key derivation process down. The slower this is, the more work 00590 * it requires being able to brute-force the resulting key. 00591 * 00592 * === Encryption 00593 * 00594 * The strategy is to first instantiate a Cipher for encryption, and 00595 * then to generate a random IV plus a key derived from the password 00596 * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt, 00597 * the number of iterations largely depends on the hardware being used. 00598 * 00599 * cipher = OpenSSL::Cipher.new 'AES-128-CBC' 00600 * cipher.encrypt 00601 * iv = cipher.random_iv 00602 * 00603 * pwd = 'some hopefully not to easily guessable password' 00604 * salt = OpenSSL::Random.random_bytes 16 00605 * iter = 20000 00606 * key_len = cipher.key_len 00607 * digest = OpenSSL::Digest::SHA256.new 00608 * 00609 * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) 00610 * cipher.key = key 00611 * 00612 * Now encrypt the data: 00613 * 00614 * encrypted = cipher.update document 00615 * encrypted << cipher.final 00616 * 00617 * === Decryption 00618 * 00619 * Use the same steps as before to derive the symmetric AES key, this time 00620 * setting the Cipher up for decryption. 00621 * 00622 * cipher = OpenSSL::Cipher.new 'AES-128-CBC' 00623 * cipher.decrypt 00624 * cipher.iv = iv # the one generated with #random_iv 00625 * 00626 * pwd = 'some hopefully not to easily guessable password' 00627 * salt = ... # the one generated above 00628 * iter = 20000 00629 * key_len = cipher.key_len 00630 * digest = OpenSSL::Digest::SHA256.new 00631 * 00632 * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) 00633 * cipher.key = key 00634 * 00635 * Now decrypt the data: 00636 * 00637 * decrypted = cipher.update encrypted 00638 * decrypted << cipher.final 00639 * 00640 * == PKCS #5 Password-based Encryption 00641 * 00642 * PKCS #5 is a password-based encryption standard documented at 00643 * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or 00644 * passphrase to be used to create a secure encryption key. If possible, PBKDF2 00645 * as described above should be used if the circumstances allow it. 00646 * 00647 * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption 00648 * key. 00649 * 00650 * pass_phrase = 'my secure pass phrase goes here' 00651 * salt = '8 octets' 00652 * 00653 * === Encryption 00654 * 00655 * First set up the cipher for encryption 00656 * 00657 * encrypter = OpenSSL::Cipher.new 'AES-128-CBC' 00658 * encrypter.encrypt 00659 * encrypter.pkcs5_keyivgen pass_phrase, salt 00660 * 00661 * Then pass the data you want to encrypt through 00662 * 00663 * encrypted = encrypter.update 'top secret document' 00664 * encrypted << encrypter.final 00665 * 00666 * === Decryption 00667 * 00668 * Use a new Cipher instance set up for decryption 00669 * 00670 * decrypter = OpenSSL::Cipher.new 'AES-128-CBC' 00671 * decrypter.decrypt 00672 * decrypter.pkcs5_keyivgen pass_phrase, salt 00673 * 00674 * Then pass the data you want to decrypt through 00675 * 00676 * plain = decrypter.update encrypted 00677 * plain << decrypter.final 00678 * 00679 * == X509 Certificates 00680 * 00681 * === Creating a Certificate 00682 * 00683 * This example creates a self-signed certificate using an RSA key and a SHA1 00684 * signature. 00685 * 00686 * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example' 00687 * 00688 * cert = OpenSSL::X509::Certificate.new 00689 * cert.version = 2 00690 * cert.serial = 0 00691 * cert.not_before = Time.now 00692 * cert.not_after = Time.now + 3600 00693 * 00694 * cert.public_key = key.public_key 00695 * cert.subject = name 00696 * 00697 * === Certificate Extensions 00698 * 00699 * You can add extensions to the certificate with 00700 * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate. 00701 * 00702 * extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert 00703 * 00704 * cert.add_extension \ 00705 * extension_factory.create_extension('basicConstraints', 'CA:FALSE', true) 00706 * 00707 * cert.add_extension \ 00708 * extension_factory.create_extension( 00709 * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature') 00710 * 00711 * cert.add_extension \ 00712 * extension_factory.create_extension('subjectKeyIdentifier', 'hash') 00713 * 00714 * The list of supported extensions (and in some cases their possible values) 00715 * can be derived from the "objects.h" file in the OpenSSL source code. 00716 * 00717 * === Signing a Certificate 00718 * 00719 * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign 00720 * with a digest algorithm. This creates a self-signed cert because we're using 00721 * the same name and key to sign the certificate as was used to create the 00722 * certificate. 00723 * 00724 * cert.issuer = name 00725 * cert.sign key, OpenSSL::Digest::SHA1.new 00726 * 00727 * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end 00728 * 00729 * === Loading a Certificate 00730 * 00731 * Like a key, a cert can also be loaded from a file. 00732 * 00733 * cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem' 00734 * 00735 * === Verifying a Certificate 00736 * 00737 * Certificate#verify will return true when a certificate was signed with the 00738 * given public key. 00739 * 00740 * raise 'certificate can not be verified' unless cert2.verify key 00741 * 00742 * == Certificate Authority 00743 * 00744 * A certificate authority (CA) is a trusted third party that allows you to 00745 * verify the ownership of unknown certificates. The CA issues key signatures 00746 * that indicate it trusts the user of that key. A user encountering the key 00747 * can verify the signature by using the CA's public key. 00748 * 00749 * === CA Key 00750 * 00751 * CA keys are valuable, so we encrypt and save it to disk and make sure it is 00752 * not readable by other users. 00753 * 00754 * ca_key = OpenSSL::PKey::RSA.new 2048 00755 * 00756 * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' 00757 * 00758 * open 'ca_key.pem', 'w', 0400 do |io| 00759 * io.write key.export(cipher, pass_phrase) 00760 * end 00761 * 00762 * === CA Certificate 00763 * 00764 * A CA certificate is created the same way we created a certificate above, but 00765 * with different extensions. 00766 * 00767 * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example' 00768 * 00769 * ca_cert = OpenSSL::X509::Certificate.new 00770 * ca_cert.serial = 0 00771 * ca_cert.version = 2 00772 * ca_cert.not_before = Time.now 00773 * ca_cert.not_after = Time.now + 86400 00774 * 00775 * ca_cert.public_key = ca_key.public_key 00776 * ca_cert.subject = ca_name 00777 * ca_cert.issuer = ca_name 00778 * 00779 * extension_factory = OpenSSL::X509::ExtensionFactory.new 00780 * extension_factory.subject_certificate = ca_cert 00781 * extension_factory.issuer_certificate = ca_cert 00782 * 00783 * ca_cert.add_extension \ 00784 * extension_factory.create_extension('subjectKeyIdentifier', 'hash') 00785 * 00786 * This extension indicates the CA's key may be used as a CA. 00787 * 00788 * ca_cert.add_extension \ 00789 * extension_factory.create_extension('basicConstraints', 'CA:TRUE', true) 00790 * 00791 * This extension indicates the CA's key may be used to verify signatures on 00792 * both certificates and certificate revocations. 00793 * 00794 * ca_cert.add_extension \ 00795 * extension_factory.create_extension( 00796 * 'keyUsage', 'cRLSign,keyCertSign', true) 00797 * 00798 * Root CA certificates are self-signed. 00799 * 00800 * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new 00801 * 00802 * The CA certificate is saved to disk so it may be distributed to all the 00803 * users of the keys this CA will sign. 00804 * 00805 * open 'ca_cert.pem', 'w' do |io| 00806 * io.write ca_cert.to_pem 00807 * end 00808 * 00809 * === Certificate Signing Request 00810 * 00811 * The CA signs keys through a Certificate Signing Request (CSR). The CSR 00812 * contains the information necessary to identify the key. 00813 * 00814 * csr = OpenSSL::X509::Request.new 00815 * csr.version = 0 00816 * csr.subject = name 00817 * csr.public_key = key.public_key 00818 * csr.sign key, OpenSSL::Digest::SHA1.new 00819 * 00820 * A CSR is saved to disk and sent to the CA for signing. 00821 * 00822 * open 'csr.pem', 'w' do |io| 00823 * io.write csr.to_pem 00824 * end 00825 * 00826 * === Creating a Certificate from a CSR 00827 * 00828 * Upon receiving a CSR the CA will verify it before signing it. A minimal 00829 * verification would be to check the CSR's signature. 00830 * 00831 * csr = OpenSSL::X509::Request.new File.read 'csr.pem' 00832 * 00833 * raise 'CSR can not be verified' unless csr.verify csr.public_key 00834 * 00835 * After verification a certificate is created, marked for various usages, 00836 * signed with the CA key and returned to the requester. 00837 * 00838 * csr_cert = OpenSSL::X509::Certificate.new 00839 * csr_cert.serial = 0 00840 * csr_cert.version = 2 00841 * csr_cert.not_before = Time.now 00842 * csr_cert.not_after = Time.now + 600 00843 * 00844 * csr_cert.subject = csr.subject 00845 * csr_cert.public_key = csr.public_key 00846 * csr_cert.issuer = ca_cert.subject 00847 * 00848 * extension_factory = OpenSSL::X509::ExtensionFactory.new 00849 * extension_factory.subject_certificate = csr_cert 00850 * extension_factory.issuer_certificate = ca_cert 00851 * 00852 * csr_cert.add_extension \ 00853 * extension_factory.create_extension('basicConstraints', 'CA:FALSE') 00854 * 00855 * csr_cert.add_extension \ 00856 * extension_factory.create_extension( 00857 * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature') 00858 * 00859 * csr_cert.add_extension \ 00860 * extension_factory.create_extension('subjectKeyIdentifier', 'hash') 00861 * 00862 * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new 00863 * 00864 * open 'csr_cert.pem', 'w' do |io| 00865 * io.write csr_cert.to_pem 00866 * end 00867 * 00868 * == SSL and TLS Connections 00869 * 00870 * Using our created key and certificate we can create an SSL or TLS connection. 00871 * An SSLContext is used to set up an SSL session. 00872 * 00873 * context = OpenSSL::SSL::SSLContext.new 00874 * 00875 * === SSL Server 00876 * 00877 * An SSL server requires the certificate and private key to communicate 00878 * securely with its clients: 00879 * 00880 * context.cert = cert 00881 * context.key = key 00882 * 00883 * Then create an SSLServer with a TCP server socket and the context. Use the 00884 * SSLServer like an ordinary TCP server. 00885 * 00886 * require 'socket' 00887 * 00888 * tcp_server = TCPServer.new 5000 00889 * ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context 00890 * 00891 * loop do 00892 * ssl_connection = ssl_server.accept 00893 * 00894 * data = connection.gets 00895 * 00896 * response = "I got #{data.dump}" 00897 * puts response 00898 * 00899 * connection.puts "I got #{data.dump}" 00900 * connection.close 00901 * end 00902 * 00903 * === SSL client 00904 * 00905 * An SSL client is created with a TCP socket and the context. 00906 * SSLSocket#connect must be called to initiate the SSL handshake and start 00907 * encryption. A key and certificate are not required for the client socket. 00908 * 00909 * require 'socket' 00910 * 00911 * tcp_client = TCPSocket.new 'localhost', 5000 00912 * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context 00913 * ssl_client.connect 00914 * 00915 * ssl_client.puts "hello server!" 00916 * puts ssl_client.gets 00917 * 00918 * === Peer Verification 00919 * 00920 * An unverified SSL connection does not provide much security. For enhanced 00921 * security the client or server can verify the certificate of its peer. 00922 * 00923 * The client can be modified to verify the server's certificate against the 00924 * certificate authority's certificate: 00925 * 00926 * context.ca_file = 'ca_cert.pem' 00927 * context.verify_mode = OpenSSL::SSL::VERIFY_PEER 00928 * 00929 * require 'socket' 00930 * 00931 * tcp_client = TCPSocket.new 'localhost', 5000 00932 * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context 00933 * ssl_client.connect 00934 * 00935 * ssl_client.puts "hello server!" 00936 * puts ssl_client.gets 00937 * 00938 * If the server certificate is invalid or <tt>context.ca_file</tt> is not set 00939 * when verifying peers an OpenSSL::SSL::SSLError will be raised. 00940 * 00941 */ 00942 void 00943 Init_openssl() 00944 { 00945 /* 00946 * Init timezone info 00947 */ 00948 #if 0 00949 tzset(); 00950 #endif 00951 00952 /* 00953 * Init all digests, ciphers 00954 */ 00955 /* CRYPTO_malloc_init(); */ 00956 /* ENGINE_load_builtin_engines(); */ 00957 OpenSSL_add_ssl_algorithms(); 00958 OpenSSL_add_all_algorithms(); 00959 ERR_load_crypto_strings(); 00960 SSL_load_error_strings(); 00961 00962 /* 00963 * FIXME: 00964 * On unload do: 00965 */ 00966 #if 0 00967 CONF_modules_unload(1); 00968 destroy_ui_method(); 00969 EVP_cleanup(); 00970 ENGINE_cleanup(); 00971 CRYPTO_cleanup_all_ex_data(); 00972 ERR_remove_state(0); 00973 ERR_free_strings(); 00974 #endif 00975 00976 /* 00977 * Init main module 00978 */ 00979 mOSSL = rb_define_module("OpenSSL"); 00980 00981 /* 00982 * OpenSSL ruby extension version 00983 */ 00984 rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION)); 00985 00986 /* 00987 * Version of OpenSSL the ruby OpenSSL extension was built with 00988 */ 00989 rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT)); 00990 00991 /* 00992 * Version number of OpenSSL the ruby OpenSSL extension was built with 00993 * (base 16) 00994 */ 00995 rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); 00996 00997 /* 00998 * Boolean indicating whether OpenSSL is FIPS-enabled or not 00999 */ 01000 #ifdef HAVE_OPENSSL_FIPS 01001 rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue); 01002 #else 01003 rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse); 01004 #endif 01005 rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1); 01006 01007 /* 01008 * Generic error, 01009 * common for all classes under OpenSSL module 01010 */ 01011 eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError); 01012 01013 /* 01014 * Verify callback Proc index for ext-data 01015 */ 01016 if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0) 01017 ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); 01018 01019 /* 01020 * Init debug core 01021 */ 01022 dOSSL = Qfalse; 01023 rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0); 01024 rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1); 01025 rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0); 01026 01027 /* 01028 * Get ID of to_der 01029 */ 01030 ossl_s_to_der = rb_intern("to_der"); 01031 01032 /* 01033 * Init components 01034 */ 01035 Init_ossl_bn(); 01036 Init_ossl_cipher(); 01037 Init_ossl_config(); 01038 Init_ossl_digest(); 01039 Init_ossl_hmac(); 01040 Init_ossl_ns_spki(); 01041 Init_ossl_pkcs12(); 01042 Init_ossl_pkcs7(); 01043 Init_ossl_pkcs5(); 01044 Init_ossl_pkey(); 01045 Init_ossl_rand(); 01046 Init_ossl_ssl(); 01047 Init_ossl_x509(); 01048 Init_ossl_ocsp(); 01049 Init_ossl_engine(); 01050 Init_ossl_asn1(); 01051 } 01052 01053 #if defined(OSSL_DEBUG) 01054 /* 01055 * Check if all symbols are OK with 'make LDSHARED=gcc all' 01056 */ 01057 int 01058 main(int argc, char *argv[]) 01059 { 01060 return 0; 01061 } 01062 #endif /* OSSL_DEBUG */ 01063 01064