|
Ruby
2.0.0p481(2014-05-08revision45883)
|
00001 /* 00002 * $Id: ossl.c 45472 2014-03-30 14:50:41Z 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 VALUE str = Qnil; 00297 const char *msg; 00298 long e; 00299 00300 #ifdef HAVE_ERR_PEEK_LAST_ERROR 00301 e = ERR_peek_last_error(); 00302 #else 00303 e = ERR_peek_error(); 00304 #endif 00305 if (fmt) { 00306 str = rb_vsprintf(fmt, args); 00307 } 00308 if (e) { 00309 if (dOSSL == Qtrue) /* FULL INFO */ 00310 msg = ERR_error_string(e, NULL); 00311 else 00312 msg = ERR_reason_error_string(e); 00313 if (NIL_P(str)) { 00314 if (msg) str = rb_str_new_cstr(msg); 00315 } 00316 else { 00317 if (RSTRING_LEN(str)) rb_str_cat2(str, ": "); 00318 rb_str_cat2(str, msg ? msg : "(null)"); 00319 } 00320 } 00321 if (dOSSL == Qtrue){ /* show all errors on the stack */ 00322 while ((e = ERR_get_error()) != 0){ 00323 rb_warn("error on stack: %s", ERR_error_string(e, NULL)); 00324 } 00325 } 00326 ERR_clear_error(); 00327 00328 if (NIL_P(str)) str = rb_str_new(0, 0); 00329 return rb_exc_new3(exc, str); 00330 } 00331 00332 void 00333 ossl_raise(VALUE exc, const char *fmt, ...) 00334 { 00335 va_list args; 00336 VALUE err; 00337 va_start(args, fmt); 00338 err = ossl_make_error(exc, fmt, args); 00339 va_end(args); 00340 rb_exc_raise(err); 00341 } 00342 00343 VALUE 00344 ossl_exc_new(VALUE exc, const char *fmt, ...) 00345 { 00346 va_list args; 00347 VALUE err; 00348 va_start(args, fmt); 00349 err = ossl_make_error(exc, fmt, args); 00350 va_end(args); 00351 return err; 00352 } 00353 00354 /* 00355 * call-seq: 00356 * OpenSSL.errors -> [String...] 00357 * 00358 * See any remaining errors held in queue. 00359 * 00360 * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation. 00361 */ 00362 VALUE 00363 ossl_get_errors() 00364 { 00365 VALUE ary; 00366 long e; 00367 00368 ary = rb_ary_new(); 00369 while ((e = ERR_get_error()) != 0){ 00370 rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL))); 00371 } 00372 00373 return ary; 00374 } 00375 00376 /* 00377 * Debug 00378 */ 00379 VALUE dOSSL; 00380 00381 #if !defined(HAVE_VA_ARGS_MACRO) 00382 void 00383 ossl_debug(const char *fmt, ...) 00384 { 00385 va_list args; 00386 00387 if (dOSSL == Qtrue) { 00388 fprintf(stderr, "OSSL_DEBUG: "); 00389 va_start(args, fmt); 00390 vfprintf(stderr, fmt, args); 00391 va_end(args); 00392 fprintf(stderr, " [CONTEXT N/A]\n"); 00393 } 00394 } 00395 #endif 00396 00397 /* 00398 * call-seq: 00399 * OpenSSL.debug -> true | false 00400 */ 00401 static VALUE 00402 ossl_debug_get(VALUE self) 00403 { 00404 return dOSSL; 00405 } 00406 00407 /* 00408 * call-seq: 00409 * OpenSSL.debug = boolean -> boolean 00410 * 00411 * Turns on or off CRYPTO_MEM_CHECK. 00412 * Also shows some debugging message on stderr. 00413 */ 00414 static VALUE 00415 ossl_debug_set(VALUE self, VALUE val) 00416 { 00417 VALUE old = dOSSL; 00418 dOSSL = val; 00419 00420 if (old != dOSSL) { 00421 if (dOSSL == Qtrue) { 00422 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 00423 fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n"); 00424 } else if (old == Qtrue) { 00425 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); 00426 fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n"); 00427 } 00428 } 00429 return val; 00430 } 00431 00432 /* 00433 * call-seq: 00434 * OpenSSL.fips_mode = boolean -> boolean 00435 * 00436 * Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an 00437 * effect for FIPS-capable installations of the OpenSSL library. Trying to do 00438 * so otherwise will result in an error. 00439 * 00440 * === Examples 00441 * 00442 * OpenSSL.fips_mode = true # turn FIPS mode on 00443 * OpenSSL.fips_mode = false # and off again 00444 */ 00445 static VALUE 00446 ossl_fips_mode_set(VALUE self, VALUE enabled) 00447 { 00448 00449 #ifdef HAVE_OPENSSL_FIPS 00450 if (RTEST(enabled)) { 00451 int mode = FIPS_mode(); 00452 if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */ 00453 ossl_raise(eOSSLError, "Turning on FIPS mode failed"); 00454 } else { 00455 if(!FIPS_mode_set(0)) /* turning off twice is OK */ 00456 ossl_raise(eOSSLError, "Turning off FIPS mode failed"); 00457 } 00458 return enabled; 00459 #else 00460 if (RTEST(enabled)) 00461 ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode"); 00462 return enabled; 00463 #endif 00464 } 00465 00466 /* 00467 * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the 00468 * OpenSSL[http://www.openssl.org/] library. 00469 * 00470 * = Examples 00471 * 00472 * All examples assume you have loaded OpenSSL with: 00473 * 00474 * require 'openssl' 00475 * 00476 * These examples build atop each other. For example the key created in the 00477 * next is used in throughout these examples. 00478 * 00479 * == Keys 00480 * 00481 * === Creating a Key 00482 * 00483 * This example creates a 2048 bit RSA keypair and writes it to the current 00484 * directory. 00485 * 00486 * key = OpenSSL::PKey::RSA.new 2048 00487 * 00488 * open 'private_key.pem', 'w' do |io| io.write key.to_pem end 00489 * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end 00490 * 00491 * === Exporting a Key 00492 * 00493 * Keys saved to disk without encryption are not secure as anyone who gets 00494 * ahold of the key may use it unless it is encrypted. In order to securely 00495 * export a key you may export it with a pass phrase. 00496 * 00497 * cipher = OpenSSL::Cipher.new 'AES-128-CBC' 00498 * pass_phrase = 'my secure pass phrase goes here' 00499 * 00500 * key_secure = key.export cipher, pass_phrase 00501 * 00502 * open 'private.secure.pem', 'w' do |io| 00503 * io.write key_secure 00504 * end 00505 * 00506 * OpenSSL::Cipher.ciphers returns a list of available ciphers. 00507 * 00508 * === Loading a Key 00509 * 00510 * A key can also be loaded from a file. 00511 * 00512 * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem' 00513 * key2.public? # => true 00514 * 00515 * or 00516 * 00517 * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem' 00518 * key3.private? # => false 00519 * 00520 * === Loading an Encrypted Key 00521 * 00522 * OpenSSL will prompt you for your pass phrase when loading an encrypted key. 00523 * If you will not be able to type in the pass phrase you may provide it when 00524 * loading the key: 00525 * 00526 * key4_pem = File.read 'private.secure.pem' 00527 * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase 00528 * 00529 * == RSA Encryption 00530 * 00531 * RSA provides encryption and decryption using the public and private keys. 00532 * You can use a variety of padding methods depending upon the intended use of 00533 * encrypted data. 00534 * 00535 * === Encryption & Decryption 00536 * 00537 * Asymmetric public/private key encryption is slow and victim to attack in 00538 * cases where it is used without padding or directly to encrypt larger chunks 00539 * of data. Typical use cases for RSA encryption involve "wrapping" a symmetric 00540 * key with the public key of the recipient who would "unwrap" that symmetric 00541 * key again using their private key. 00542 * The following illustrates a simplified example of such a key transport 00543 * scheme. It shouldn't be used in practice, though, standardized protocols 00544 * should always be preferred. 00545 * 00546 * wrapped_key = key.public_encrypt key 00547 * 00548 * A symmetric key encrypted with the public key can only be decrypted with 00549 * the corresponding private key of the recipient. 00550 * 00551 * original_key = key.private_decrypt wrapped_key 00552 * 00553 * By default PKCS#1 padding will be used, but it is also possible to use 00554 * other forms of padding, see PKey::RSA for further details. 00555 * 00556 * === Signatures 00557 * 00558 * Using "private_encrypt" to encrypt some data with the private key is 00559 * equivalent to applying a digital signature to the data. A verifying 00560 * party may validate the signature by comparing the result of decrypting 00561 * the signature with "public_decrypt" to the original data. However, 00562 * OpenSSL::PKey already has methods "sign" and "verify" that handle 00563 * digital signatures in a standardized way - "private_encrypt" and 00564 * "public_decrypt" shouldn't be used in practice. 00565 * 00566 * To sign a document, a cryptographically secure hash of the document is 00567 * computed first, which is then signed using the private key. 00568 * 00569 * digest = OpenSSL::Digest::SHA256.new 00570 * signature = key.sign digest, document 00571 * 00572 * To validate the signature, again a hash of the document is computed and 00573 * the signature is decrypted using the public key. The result is then 00574 * compared to the hash just computed, if they are equal the signature was 00575 * valid. 00576 * 00577 * digest = OpenSSL::Digest::SHA256.new 00578 * if key.verify digest, signature, document 00579 * puts 'Valid' 00580 * else 00581 * puts 'Invalid' 00582 * end 00583 * 00584 * == PBKDF2 Password-based Encryption 00585 * 00586 * If supported by the underlying OpenSSL version used, Password-based 00587 * Encryption should use the features of PKCS5. If not supported or if 00588 * required by legacy applications, the older, less secure methods specified 00589 * in RFC 2898 are also supported (see below). 00590 * 00591 * PKCS5 supports PBKDF2 as it was specified in PKCS#5 00592 * v2.0[http://www.rsa.com/rsalabs/node.asp?id=2127]. It still uses a 00593 * password, a salt, and additionally a number of iterations that will 00594 * slow the key derivation process down. The slower this is, the more work 00595 * it requires being able to brute-force the resulting key. 00596 * 00597 * === Encryption 00598 * 00599 * The strategy is to first instantiate a Cipher for encryption, and 00600 * then to generate a random IV plus a key derived from the password 00601 * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt, 00602 * the number of iterations largely depends on the hardware being used. 00603 * 00604 * cipher = OpenSSL::Cipher.new 'AES-128-CBC' 00605 * cipher.encrypt 00606 * iv = cipher.random_iv 00607 * 00608 * pwd = 'some hopefully not to easily guessable password' 00609 * salt = OpenSSL::Random.random_bytes 16 00610 * iter = 20000 00611 * key_len = cipher.key_len 00612 * digest = OpenSSL::Digest::SHA256.new 00613 * 00614 * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) 00615 * cipher.key = key 00616 * 00617 * Now encrypt the data: 00618 * 00619 * encrypted = cipher.update document 00620 * encrypted << cipher.final 00621 * 00622 * === Decryption 00623 * 00624 * Use the same steps as before to derive the symmetric AES key, this time 00625 * setting the Cipher up for decryption. 00626 * 00627 * cipher = OpenSSL::Cipher.new 'AES-128-CBC' 00628 * cipher.decrypt 00629 * cipher.iv = iv # the one generated with #random_iv 00630 * 00631 * pwd = 'some hopefully not to easily guessable password' 00632 * salt = ... # the one generated above 00633 * iter = 20000 00634 * key_len = cipher.key_len 00635 * digest = OpenSSL::Digest::SHA256.new 00636 * 00637 * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) 00638 * cipher.key = key 00639 * 00640 * Now decrypt the data: 00641 * 00642 * decrypted = cipher.update encrypted 00643 * decrypted << cipher.final 00644 * 00645 * == PKCS #5 Password-based Encryption 00646 * 00647 * PKCS #5 is a password-based encryption standard documented at 00648 * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or 00649 * passphrase to be used to create a secure encryption key. If possible, PBKDF2 00650 * as described above should be used if the circumstances allow it. 00651 * 00652 * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption 00653 * key. 00654 * 00655 * pass_phrase = 'my secure pass phrase goes here' 00656 * salt = '8 octets' 00657 * 00658 * === Encryption 00659 * 00660 * First set up the cipher for encryption 00661 * 00662 * encrypter = OpenSSL::Cipher.new 'AES-128-CBC' 00663 * encrypter.encrypt 00664 * encrypter.pkcs5_keyivgen pass_phrase, salt 00665 * 00666 * Then pass the data you want to encrypt through 00667 * 00668 * encrypted = encrypter.update 'top secret document' 00669 * encrypted << encrypter.final 00670 * 00671 * === Decryption 00672 * 00673 * Use a new Cipher instance set up for decryption 00674 * 00675 * decrypter = OpenSSL::Cipher.new 'AES-128-CBC' 00676 * decrypter.decrypt 00677 * decrypter.pkcs5_keyivgen pass_phrase, salt 00678 * 00679 * Then pass the data you want to decrypt through 00680 * 00681 * plain = decrypter.update encrypted 00682 * plain << decrypter.final 00683 * 00684 * == X509 Certificates 00685 * 00686 * === Creating a Certificate 00687 * 00688 * This example creates a self-signed certificate using an RSA key and a SHA1 00689 * signature. 00690 * 00691 * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example' 00692 * 00693 * cert = OpenSSL::X509::Certificate.new 00694 * cert.version = 2 00695 * cert.serial = 0 00696 * cert.not_before = Time.now 00697 * cert.not_after = Time.now + 3600 00698 * 00699 * cert.public_key = key.public_key 00700 * cert.subject = name 00701 * 00702 * === Certificate Extensions 00703 * 00704 * You can add extensions to the certificate with 00705 * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate. 00706 * 00707 * extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert 00708 * 00709 * cert.add_extension \ 00710 * extension_factory.create_extension('basicConstraints', 'CA:FALSE', true) 00711 * 00712 * cert.add_extension \ 00713 * extension_factory.create_extension( 00714 * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature') 00715 * 00716 * cert.add_extension \ 00717 * extension_factory.create_extension('subjectKeyIdentifier', 'hash') 00718 * 00719 * The list of supported extensions (and in some cases their possible values) 00720 * can be derived from the "objects.h" file in the OpenSSL source code. 00721 * 00722 * === Signing a Certificate 00723 * 00724 * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign 00725 * with a digest algorithm. This creates a self-signed cert because we're using 00726 * the same name and key to sign the certificate as was used to create the 00727 * certificate. 00728 * 00729 * cert.issuer = name 00730 * cert.sign key, OpenSSL::Digest::SHA1.new 00731 * 00732 * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end 00733 * 00734 * === Loading a Certificate 00735 * 00736 * Like a key, a cert can also be loaded from a file. 00737 * 00738 * cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem' 00739 * 00740 * === Verifying a Certificate 00741 * 00742 * Certificate#verify will return true when a certificate was signed with the 00743 * given public key. 00744 * 00745 * raise 'certificate can not be verified' unless cert2.verify key 00746 * 00747 * == Certificate Authority 00748 * 00749 * A certificate authority (CA) is a trusted third party that allows you to 00750 * verify the ownership of unknown certificates. The CA issues key signatures 00751 * that indicate it trusts the user of that key. A user encountering the key 00752 * can verify the signature by using the CA's public key. 00753 * 00754 * === CA Key 00755 * 00756 * CA keys are valuable, so we encrypt and save it to disk and make sure it is 00757 * not readable by other users. 00758 * 00759 * ca_key = OpenSSL::PKey::RSA.new 2048 00760 * 00761 * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' 00762 * 00763 * open 'ca_key.pem', 'w', 0400 do |io| 00764 * io.write key.export(cipher, pass_phrase) 00765 * end 00766 * 00767 * === CA Certificate 00768 * 00769 * A CA certificate is created the same way we created a certificate above, but 00770 * with different extensions. 00771 * 00772 * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example' 00773 * 00774 * ca_cert = OpenSSL::X509::Certificate.new 00775 * ca_cert.serial = 0 00776 * ca_cert.version = 2 00777 * ca_cert.not_before = Time.now 00778 * ca_cert.not_after = Time.now + 86400 00779 * 00780 * ca_cert.public_key = ca_key.public_key 00781 * ca_cert.subject = ca_name 00782 * ca_cert.issuer = ca_name 00783 * 00784 * extension_factory = OpenSSL::X509::ExtensionFactory.new 00785 * extension_factory.subject_certificate = ca_cert 00786 * extension_factory.issuer_certificate = ca_cert 00787 * 00788 * ca_cert.add_extension \ 00789 * extension_factory.create_extension('subjectKeyIdentifier', 'hash') 00790 * 00791 * This extension indicates the CA's key may be used as a CA. 00792 * 00793 * ca_cert.add_extension \ 00794 * extension_factory.create_extension('basicConstraints', 'CA:TRUE', true) 00795 * 00796 * This extension indicates the CA's key may be used to verify signatures on 00797 * both certificates and certificate revocations. 00798 * 00799 * ca_cert.add_extension \ 00800 * extension_factory.create_extension( 00801 * 'keyUsage', 'cRLSign,keyCertSign', true) 00802 * 00803 * Root CA certificates are self-signed. 00804 * 00805 * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new 00806 * 00807 * The CA certificate is saved to disk so it may be distributed to all the 00808 * users of the keys this CA will sign. 00809 * 00810 * open 'ca_cert.pem', 'w' do |io| 00811 * io.write ca_cert.to_pem 00812 * end 00813 * 00814 * === Certificate Signing Request 00815 * 00816 * The CA signs keys through a Certificate Signing Request (CSR). The CSR 00817 * contains the information necessary to identify the key. 00818 * 00819 * csr = OpenSSL::X509::Request.new 00820 * csr.version = 0 00821 * csr.subject = name 00822 * csr.public_key = key.public_key 00823 * csr.sign key, OpenSSL::Digest::SHA1.new 00824 * 00825 * A CSR is saved to disk and sent to the CA for signing. 00826 * 00827 * open 'csr.pem', 'w' do |io| 00828 * io.write csr.to_pem 00829 * end 00830 * 00831 * === Creating a Certificate from a CSR 00832 * 00833 * Upon receiving a CSR the CA will verify it before signing it. A minimal 00834 * verification would be to check the CSR's signature. 00835 * 00836 * csr = OpenSSL::X509::Request.new File.read 'csr.pem' 00837 * 00838 * raise 'CSR can not be verified' unless csr.verify csr.public_key 00839 * 00840 * After verification a certificate is created, marked for various usages, 00841 * signed with the CA key and returned to the requester. 00842 * 00843 * csr_cert = OpenSSL::X509::Certificate.new 00844 * csr_cert.serial = 0 00845 * csr_cert.version = 2 00846 * csr_cert.not_before = Time.now 00847 * csr_cert.not_after = Time.now + 600 00848 * 00849 * csr_cert.subject = csr.subject 00850 * csr_cert.public_key = csr.public_key 00851 * csr_cert.issuer = ca_cert.subject 00852 * 00853 * extension_factory = OpenSSL::X509::ExtensionFactory.new 00854 * extension_factory.subject_certificate = csr_cert 00855 * extension_factory.issuer_certificate = ca_cert 00856 * 00857 * csr_cert.add_extension \ 00858 * extension_factory.create_extension('basicConstraints', 'CA:FALSE') 00859 * 00860 * csr_cert.add_extension \ 00861 * extension_factory.create_extension( 00862 * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature') 00863 * 00864 * csr_cert.add_extension \ 00865 * extension_factory.create_extension('subjectKeyIdentifier', 'hash') 00866 * 00867 * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new 00868 * 00869 * open 'csr_cert.pem', 'w' do |io| 00870 * io.write csr_cert.to_pem 00871 * end 00872 * 00873 * == SSL and TLS Connections 00874 * 00875 * Using our created key and certificate we can create an SSL or TLS connection. 00876 * An SSLContext is used to set up an SSL session. 00877 * 00878 * context = OpenSSL::SSL::SSLContext.new 00879 * 00880 * === SSL Server 00881 * 00882 * An SSL server requires the certificate and private key to communicate 00883 * securely with its clients: 00884 * 00885 * context.cert = cert 00886 * context.key = key 00887 * 00888 * Then create an SSLServer with a TCP server socket and the context. Use the 00889 * SSLServer like an ordinary TCP server. 00890 * 00891 * require 'socket' 00892 * 00893 * tcp_server = TCPServer.new 5000 00894 * ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context 00895 * 00896 * loop do 00897 * ssl_connection = ssl_server.accept 00898 * 00899 * data = connection.gets 00900 * 00901 * response = "I got #{data.dump}" 00902 * puts response 00903 * 00904 * connection.puts "I got #{data.dump}" 00905 * connection.close 00906 * end 00907 * 00908 * === SSL client 00909 * 00910 * An SSL client is created with a TCP socket and the context. 00911 * SSLSocket#connect must be called to initiate the SSL handshake and start 00912 * encryption. A key and certificate are not required for the client socket. 00913 * 00914 * require 'socket' 00915 * 00916 * tcp_client = TCPSocket.new 'localhost', 5000 00917 * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context 00918 * ssl_client.connect 00919 * 00920 * ssl_client.puts "hello server!" 00921 * puts ssl_client.gets 00922 * 00923 * === Peer Verification 00924 * 00925 * An unverified SSL connection does not provide much security. For enhanced 00926 * security the client or server can verify the certificate of its peer. 00927 * 00928 * The client can be modified to verify the server's certificate against the 00929 * certificate authority's certificate: 00930 * 00931 * context.ca_file = 'ca_cert.pem' 00932 * context.verify_mode = OpenSSL::SSL::VERIFY_PEER 00933 * 00934 * require 'socket' 00935 * 00936 * tcp_client = TCPSocket.new 'localhost', 5000 00937 * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context 00938 * ssl_client.connect 00939 * 00940 * ssl_client.puts "hello server!" 00941 * puts ssl_client.gets 00942 * 00943 * If the server certificate is invalid or <tt>context.ca_file</tt> is not set 00944 * when verifying peers an OpenSSL::SSL::SSLError will be raised. 00945 * 00946 */ 00947 void 00948 Init_openssl() 00949 { 00950 /* 00951 * Init timezone info 00952 */ 00953 #if 0 00954 tzset(); 00955 #endif 00956 00957 /* 00958 * Init all digests, ciphers 00959 */ 00960 /* CRYPTO_malloc_init(); */ 00961 /* ENGINE_load_builtin_engines(); */ 00962 OpenSSL_add_ssl_algorithms(); 00963 OpenSSL_add_all_algorithms(); 00964 ERR_load_crypto_strings(); 00965 SSL_load_error_strings(); 00966 00967 /* 00968 * FIXME: 00969 * On unload do: 00970 */ 00971 #if 0 00972 CONF_modules_unload(1); 00973 destroy_ui_method(); 00974 EVP_cleanup(); 00975 ENGINE_cleanup(); 00976 CRYPTO_cleanup_all_ex_data(); 00977 ERR_remove_state(0); 00978 ERR_free_strings(); 00979 #endif 00980 00981 /* 00982 * Init main module 00983 */ 00984 mOSSL = rb_define_module("OpenSSL"); 00985 00986 /* 00987 * OpenSSL ruby extension version 00988 */ 00989 rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION)); 00990 00991 /* 00992 * Version of OpenSSL the ruby OpenSSL extension was built with 00993 */ 00994 rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT)); 00995 00996 /* 00997 * Version number of OpenSSL the ruby OpenSSL extension was built with 00998 * (base 16) 00999 */ 01000 rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); 01001 01002 /* 01003 * Boolean indicating whether OpenSSL is FIPS-enabled or not 01004 */ 01005 #ifdef HAVE_OPENSSL_FIPS 01006 rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue); 01007 #else 01008 rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse); 01009 #endif 01010 rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1); 01011 01012 /* 01013 * Generic error, 01014 * common for all classes under OpenSSL module 01015 */ 01016 eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError); 01017 01018 /* 01019 * Verify callback Proc index for ext-data 01020 */ 01021 if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0) 01022 ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); 01023 01024 /* 01025 * Init debug core 01026 */ 01027 dOSSL = Qfalse; 01028 rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0); 01029 rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1); 01030 rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0); 01031 01032 /* 01033 * Get ID of to_der 01034 */ 01035 ossl_s_to_der = rb_intern("to_der"); 01036 01037 /* 01038 * Init components 01039 */ 01040 Init_ossl_bn(); 01041 Init_ossl_cipher(); 01042 Init_ossl_config(); 01043 Init_ossl_digest(); 01044 Init_ossl_hmac(); 01045 Init_ossl_ns_spki(); 01046 Init_ossl_pkcs12(); 01047 Init_ossl_pkcs7(); 01048 Init_ossl_pkcs5(); 01049 Init_ossl_pkey(); 01050 Init_ossl_rand(); 01051 Init_ossl_ssl(); 01052 Init_ossl_x509(); 01053 Init_ossl_ocsp(); 01054 Init_ossl_engine(); 01055 Init_ossl_asn1(); 01056 } 01057 01058 #if defined(OSSL_DEBUG) 01059 /* 01060 * Check if all symbols are OK with 'make LDSHARED=gcc all' 01061 */ 01062 int 01063 main(int argc, char *argv[]) 01064 { 01065 return 0; 01066 } 01067 #endif /* OSSL_DEBUG */ 01068 01069
1.7.6.1