|
|
James Yonan wrote: > Thanks for the interesting information on PKCS#11, OpenSSL, and smartcards. You are welcome... I now doing a phase on all open-source projects that uses cryptographic but do not use smartcards... In a standard way... :) > Any rough idea on what percentage of the cheaply available smartcards out there can talk to OpenSSL via PKCS#11? It depends on what cheap is for you... It can be rage from $12 in large numbers to $40 in ones... Aladdin USB token (www.ealaddin.com) is about $40 for one, but it does not need a reader. Athana smartcards (www.athena-scs.com) is about $17 for ones but it requires a reader that is about $20. Both works well... Aladdin uses opensc and there is opensc-pkcs#11 provider. Athena provides PKCS#11 library. > Is this part of the OpenSC effort and/or does it obsolete it? Opensc is an effort to produce open smartcard interface... But it failed. Currently there are two interfaces to access smartcards: 1. PKCS#11 of RSA Security (www.rsasecurity.com/rsalabs/node.asp?id=2133) - cross-platform free API. 2. Microsoft Cryptographic Service Provider (CSP) - Microsoft specific interface. There is a PKCS#11 provider for opensc, so that if you have opensc card you can use it with applications that uses PKCS#11. > Is this capability of using OpenSSL + PKCS#11 something which is intended to provide access to smartcards on *nix systems only, or does > it work on Windows as well? >From what I've read it works on Windows as well. http://www.opensc.org/files/doc/opensc.html#opensc.install.windowsopenssl http://www.opensc.org/files/doc/opensc.html#opensc.using.openssl (Refer to the last line of this section) > So from what you are saying, I take it that PKCS#11 smartcard support is easily accessible from OpenVPN, if only the new directives > load-engine and tls-engine are coded? True... But it is not ideal... Since the engine knows only use the private key on the smartcard... The user must extract his certificate and put it in a PEM file... But this is a good start... You should do it only to tls key negotiation... The symmetric operations of the TLS should remain as-as since the performance of smartcards are not so good... But if you want to work with future hardware accelerator for symmetric operation you should also allow specifying an engine for that purpose. > If this is the case, I would be happy to accept a patch which adds these directives. If you don't feel like coding it, it would be helpful if you > could point us at some sample code which shows the appropriate OpenSSL calls. Hmmm... This is exactly the problem... I've never got into the openssl coding... I think it is a very complex API... Usually I supply patches... If I to write patch I will use PKCS#11 directly... This is the best way to go... If you can separate the RSA operation using the private key from the key negotiation to an atomic location, or refer me to that place if it is already exist, I will try to implement the RSA using PKCS#11 and from there we can continue to use the certificate from the smartcard and then you can close up by adding the configuration options. Regarding openssl... If you point me to the point in source where this modification should be done, I will try to... Anyway, I will be happy to test what ever you like!!! I hope it will work... Since the "openssl s_client" does not work correctly... :( But here are some points you can refer to... I've looked at the source of the openssl command in order to know how to load engines. The name of the private key file should be slot_#-id_#, this way the engine finds his private key. You can look at engine.pod at openssl tar. I<Issuing control commands to an ENGINE> ALON>>> This way you load the dynamic engine giving all the pre command and post commands, all these should be taken from configuration. ALON>>> Something like: ALON>>> openssl-engine-name dynamic ALON>>> openssl-engine-pre prm1 prm2 prm3 prm4 ALON>>> openssl-engine-post prm1 prm2 prm3 prm4 ALON>>> ALON>>> Please notice that you should support of loading several engines... ALON>>> The same command is used when you use the engine command in openssl, refer to http://www.opensc.org/files/doc/opensc.html#opensc.using.openssl Let's illustrate by example; a function for which the caller supplies the name of the ENGINE it wishes to use, a table of string-pairs for use before initialization, and another table for use after initialization. Note that the string-pairs used for control commands consist of a command "name" followed by the command "parameter" - the parameter could be NULL in some cases but the name can not. This function should initialize the ENGINE (issuing the "pre" commands beforehand and the "post" commands afterwards) and set it as the default for everything except RAND and then return a boolean success or failure. int generic_load_engine_fn(const char *engine_id, const char **pre_cmds, int pre_num, const char **post_cmds, int post_num) { ENGINE *e = ENGINE_by_id(engine_id); if(!e) return 0; while(pre_num--) { if(!ENGINE_ctrl_cmd_string(e, pre_cmds[0], pre_cmds[1], 0)) { fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id, pre_cmds[0], pre_cmds[1] ? pre_cmds[1] : "(NULL)"); ENGINE_free(e); return 0; } pre_cmds += 2; } if(!ENGINE_init(e)) { fprintf(stderr, "Failed initialisation\n"); ENGINE_free(e); return 0; } /* ENGINE_init() returned a functional reference, so free the structural * reference from ENGINE_by_id(). */ ENGINE_free(e); while(post_num--) { if(!ENGINE_ctrl_cmd_string(e, post_cmds[0], post_cmds[1], 0)) { fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id, post_cmds[0], post_cmds[1] ? post_cmds[1] : "(NULL)"); ENGINE_finish(e); return 0; } post_cmds += 2; } ENGINE_set_default(e, ENGINE_METHOD_ALL & ~ENGINE_METHOD_RAND); /* Success */ return 1; } Note that ENGINE_ctrl_cmd_string() accepts a boolean argument that can relax the semantics of the function - if set non-zero it will only return failure if the ENGINE supported the given command name but failed while executing it, if the ENGINE doesn't support the command name it will simply return success without doing anything. In this case we assume the user is only supplying commands specific to the given ENGINE so we set this to FALSE. I<Using a specific ENGINE implementation> ALON>>> This is used to use a specific engine. ALON>>> After loading a dynamic engine a name is given to it. Here we'll assume an application has been configured by its user or admin to want to use the "ACME" ENGINE if it is available in the version of OpenSSL the application was compiled with. If it is available, it should be used by default for all RSA, DSA, and symmetric cipher operation, otherwise OpenSSL should use its builtin software as per usual. The following code illustrates how to approach this; ENGINE *e; const char *engine_id = "ACME"; ENGINE_load_builtin_engines(); e = ENGINE_by_id(engine_id); if(!e) /* the engine isn't available */ return; if(!ENGINE_init(e)) { /* the engine couldn't initialise, release 'e' */ ENGINE_free(e); return; } if(!ENGINE_set_default_RSA(e)) /* This should only happen when 'e' can't initialise, but the previous * statement suggests it did. */ abort(); ENGINE_set_default_DSA(e); ENGINE_set_default_ciphers(e); /* Release the functional reference from ENGINE_init() */ ENGINE_finish(e); /* Release the structural reference from ENGINE_by_id() */ ENGINE_free(e); Best Regards, Alon Bar-Lev. |