|
reSIProcate/stack
9694
|
00001 #include <openssl/ssl.h> 00002 #include <openssl/pem.h> 00003 #include <openssl/ossl_typ.h> 00004 #include <openssl/x509.h> 00005 #include <openssl/x509v3.h> 00006 #include <openssl/err.h> 00007 #include "resip/stack/X509Contents.hxx" 00008 #include "resip/stack/Pkcs8Contents.hxx" 00009 #include "resip/stack/MultipartMixedContents.hxx" 00010 #include "resip/stack/Uri.hxx" 00011 #include "rutil/Random.hxx" 00012 #include "rutil/Logger.hxx" 00013 00014 using namespace resip; 00015 00016 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP 00017 00018 int makeSelfCert(X509** selfcert, EVP_PKEY* privkey); 00019 00020 int main(int argc, char* argv[]) 00021 { 00022 int stat; 00023 Uri aor; 00024 Data passphrase("password"); 00025 RSA *rsa = NULL; 00026 EVP_PKEY *privkey = NULL; 00027 X509 *selfcert = NULL; 00028 BUF_MEM *bptr = NULL; 00029 00030 Log::initialize(Log::Cerr, Log::Err, argv[0]); 00031 Log::setLevel(Log::Debug); 00032 SSL_library_init(); 00033 SSL_load_error_strings(); 00034 OpenSSL_add_all_algorithms(); 00035 //OpenSSL_add_ssl_algorithms() is insufficient here... 00036 00037 // make sure that necessary algorithms exist: 00038 assert(EVP_des_ede3_cbc()); 00039 00040 Random::initialize(); 00041 00042 rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); 00043 assert(rsa); // couldn't make key pair 00044 00045 // TODO: remove this once we've tested this 00046 stat = PEM_write_RSAPrivateKey( stdout, rsa, NULL, NULL, 0, NULL, NULL); // Write this out for debugging 00047 00048 privkey = EVP_PKEY_new(); 00049 assert(privkey); 00050 stat = EVP_PKEY_set1_RSA(privkey, rsa); 00051 assert(stat); 00052 00053 selfcert = X509_new(); 00054 assert(selfcert); 00055 stat = makeSelfCert(&selfcert, privkey); 00056 assert(stat); // couldn't make cert 00057 00058 unsigned char* buffer = NULL; 00059 int len = i2d_X509(selfcert, &buffer); // if buffer is NULL, openssl 00060 // assigns memory for buffer 00061 assert(buffer); 00062 Data derData((char *) buffer, len); 00063 X509Contents *certpart = new X509Contents( derData ); 00064 assert(certpart); 00065 00066 // TDOD: remove later, just useful for debugging 00067 // stat = PEM_write_PKCS8PrivateKey( stdout, privkey, NULL, NULL, 0, NULL, NULL); 00068 00069 // make an in-memory BIO [ see BIO_s_mem(3) ] 00070 BIO *mbio = BIO_new(BIO_s_mem()); 00071 assert(mbio); 00072 00073 // encrypt the the private key with the passphrase and put it in the BIO in DER format 00074 stat = i2d_PKCS8PrivateKey_bio( mbio, privkey, EVP_des_ede3_cbc(), 00075 (char *) passphrase.data(), passphrase.size(), NULL, NULL); 00076 assert(stat); 00077 00078 // dump the BIO into a Contents and free the BIO 00079 BIO_get_mem_ptr(mbio, &bptr); 00080 Pkcs8Contents *keypart = new Pkcs8Contents(Data(bptr->data, bptr->length)); 00081 assert(keypart); 00082 BIO_free(mbio); 00083 00084 // make the multipart body 00085 MultipartMixedContents *certsbody = new MultipartMixedContents; 00086 certsbody->parts().push_back(certpart); 00087 certsbody->parts().push_back(keypart); 00088 assert(certsbody); 00089 00090 Data foo; 00091 DataStream foostr(foo); 00092 certsbody->encode(foostr); 00093 foostr.flush(); 00094 00095 DebugLog ( << foo ); 00096 } 00097 00098 00099 int makeSelfCert(X509 **cert, EVP_PKEY *privkey) // should include a Uri type at the end of the function call 00100 { 00101 int stat; 00102 int serial; 00103 assert(sizeof(int)==4); 00104 const long duration = 60*60*24*30; // make cert valid for 30 days 00105 X509* selfcert = NULL; 00106 X509_NAME *subject = NULL; 00107 X509_EXTENSION *ext = NULL; 00108 00109 Data domain("example.org"); 00110 Data userAtDomain("user@example.org"); 00111 00112 // Setup the subjectAltName structure here with sip:, im:, and pres: URIs 00113 // TODO: 00114 00115 selfcert = *cert; 00116 subject = X509_NAME_new(); 00117 ext = X509_EXTENSION_new(); 00118 00119 X509_set_version(selfcert, 2L); // set version to X509v3 (starts from 0) 00120 00121 // RAND_bytes((char *) serial , 4); 00122 //serial = 1; 00123 serial = Random::getRandom(); // get an int worth of randomness 00124 ASN1_INTEGER_set(X509_get_serialNumber(selfcert),serial); 00125 00126 stat = X509_NAME_add_entry_by_txt( subject, "O", MBSTRING_UTF8, (unsigned char *) domain.data(), domain.size(), -1, 0); 00127 assert(stat); 00128 stat = X509_NAME_add_entry_by_txt( subject, "CN", MBSTRING_UTF8, (unsigned char *) userAtDomain.data(), userAtDomain.size(), -1, 0); 00129 assert(stat); 00130 00131 stat = X509_set_issuer_name(selfcert, subject); 00132 assert(stat); 00133 stat = X509_set_subject_name(selfcert, subject); 00134 assert(stat); 00135 00136 X509_gmtime_adj(X509_get_notBefore(selfcert),0); 00137 X509_gmtime_adj(X509_get_notAfter(selfcert), duration); 00138 00139 stat = X509_set_pubkey(selfcert, privkey); 00140 assert(stat); 00141 00142 // need to fiddle with this to make this work with lists of IA5 URIs and UTF8 00143 // using GENERAL_NAMES seems like a promissing approach 00144 // (search for GENERAL_NAMES in Security.cxx) 00145 // 00146 //ext = X509V3_EXT_conf_nid( NULL , NULL , NID_subject_alt_name, subjectAltNameStr.cstr() ); 00147 //X509_add_ext( selfcert, ext, -1); 00148 //X509_EXTENSION_free(ext); 00149 00150 static char CA_FALSE[] = "CA:FALSE"; 00151 ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, CA_FALSE); 00152 stat = X509_add_ext( selfcert, ext, -1); 00153 assert(stat); 00154 X509_EXTENSION_free(ext); 00155 00156 // add extensions NID_subject_key_identifier and NID_authority_key_identifier 00157 00158 stat = X509_sign(selfcert, privkey, EVP_sha1()); 00159 assert(stat); 00160 00161 return true; 00162 } 00163 00164 /* ==================================================================== 00165 * The Vovida Software License, Version 1.0 00166 * 00167 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00168 * 00169 * Redistribution and use in source and binary forms, with or without 00170 * modification, are permitted provided that the following conditions 00171 * are met: 00172 * 00173 * 1. Redistributions of source code must retain the above copyright 00174 * notice, this list of conditions and the following disclaimer. 00175 * 00176 * 2. Redistributions in binary form must reproduce the above copyright 00177 * notice, this list of conditions and the following disclaimer in 00178 * the documentation and/or other materials provided with the 00179 * distribution. 00180 * 00181 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00182 * and "Vovida Open Communication Application Library (VOCAL)" must 00183 * not be used to endorse or promote products derived from this 00184 * software without prior written permission. For written 00185 * permission, please contact vocal@vovida.org. 00186 * 00187 * 4. Products derived from this software may not be called "VOCAL", nor 00188 * may "VOCAL" appear in their name, without prior written 00189 * permission of Vovida Networks, Inc. 00190 * 00191 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00192 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00193 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00194 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00195 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00196 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00197 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00198 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00199 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00200 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00201 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00202 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00203 * DAMAGE. 00204 * 00205 * ==================================================================== 00206 * 00207 * This software consists of voluntary contributions made by Vovida 00208 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00209 * Inc. For more information on Vovida Networks, Inc., please see 00210 * <http://www.vovida.org/>. 00211 * 00212 */
1.7.5.1