Network Security with OpenSSL by John Viega, Matt Messier, Pravir Chandra The unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification This page was updated August 6, 2008. UNCONFIRMED errors and comments from readers: (35) 2nd example; Example as given : 9780596002701 enc -des3-ede-ofb -d -in ciphertext.bin -out plaintext.doc -pass pass:trousers This generates an error. Example that works : 9780596002701 enc -des-ede3-ofb -d -in ciphertext.bin -out plaintext.doc -pass pass:trousers NOTE: difference is -des3-ede-ofb VS -des-ede3-ofb [48]5th paragraph, 3rd sentence; (perhaps due to certificate theft) should be (perhaps due to private key theft) [50]2nd paragraph, 2nd sentence; "As with the keyUsage extension, if this extension is present, it should be designated critical." This is wrong. See RFC 3280, section 4.2.1.13, paragraph 5: "This extension MAY, at the option of the certificate issuer, be either critical or non-critical." {65} 4th line (command); It seems that the "openssl" command cannot get the number of days and bits set in the configuration file cannot be taken (so it is a problem of the "openssl" command itself). The following command works OK: openssl req -config /opt/TMBca/openssl.cnf -x509 -newkey rsa:2048 -days 365 -out cacert.pem -outform PEM Without specifying the days in the command line, then the number of days is one month (irrespective of the fact that in the configuration file it is set as 365). (65) Example 3-5; The command: # 9780596002701 req -x509 -newkey rsa -out cacert.pem -outform PEM (lines 4 and 16) would not generate the validity of 1 year (365 days) for the self-signed root certificate as shown in example 3-5. With reference to "req" man-page, the option "-days 365" is required when using "-x509" to generate a validity of 365 days; otherwise the default validity is 30 days. {68} Example 3-7; Attributes: unstructuredName :drowssap egnellahc challengePassword :drowssap egnellahc Should be: (Tested under OpenSSH 0.9.7a) Attributes: unstructuredName :Examples-R-Us, Inc. challengePassword :cloud noon sundry presto madrid baker {84} Last paragraph; The described error function: char *ERR_error_string_n(unsigned long e, char *buf, size_t len); should be: void ERR_error_string_n(unsigned long e, char *buf, size_t len); at least for OpenSSL 0.9.6.d... (86) last line; The prototype of the function shown in the last line is prepended with the word "The". However this would not result in valid C code and I assume it is a leftover from some editing of the line/paragraph. [101] 1st paragraph in "Using an Alternate Entropy Source"; "It is licensed under the BSD licence, which means that it's free and the source code is available." should read: "It is licensed under GPL (version 2), which means the source code is freely available; see http://www.gnu.org/copyleft/gpl.html for details." {107} Table 4-1; (r = pow(a, 2) % m) should be (r = pow(a, p) % m) for BN_mod_exp(r, a, p, m, ctx) {114} Example 5-1, line 17 (THREAD_CREATE macro); The THREAD_CREATE macro (for windows) appears to attempt to return an identifier for the newly created thread. The code, however, will always return the id of the thread that called the macro. To return the identifier of the new thread the macro should be modified so read:- #define THREAD_CREATE(tid, entry, arg) do { \ (tid) = GetThreadId (_beginthread ((entry), 0, (arg))) \ } while (0); Because 'GetThreadId' uses the handle returned by _beginthread to retrieve the identifier of the newly created thread. [115] example 5-3; the for loop: for (nwritten = 0; nwritten < sizeof(buf); nwritten += err) should be: for (nwritten = 0; nwritten < strlen(buf); nwritten += err) {117} all following examples; Examples 4-9 through 4-12 define a function seed_prng() defined as: int seed_prng(int bytes) But in several of client/server examples in Chapter 5 (Examples 5-5, 5-6, 5-9, and 5- 10) the usage appears to be void seed_prng(void). Suggest changing the Chapter 5 examples to show: seed_prng(1024); {117} Line 21; server_thread() function should return pointer (to suppress compile warning). So line 21 should read: void *THREAD_CC server_thread(void *arg) rather than void THREAD_CC server_thread(void *arg) [124] 3rd paragraph; my9780596002701.cnf file is missing. I believe that openssl.cnf is what was intended. It should be located in /etc/ssl/9780596002701.cnf [124] examples of how to create certificates; my9780596002701.cnf is missing although it is used in several examples to create certificates. That leaves readers in guessing state and unable to try the examples out themselves. {125} 1st paragraph; "Line 56 does this through a call to SSL_set_bio." should read: "Line 55 does this through a call to SSL_set_bio." [136] Example 5-8 (function post_connection_check); The function post_connection_check() in example 5-8 uses internal functions from the OpenSSL library instead of stable functions from the public API. This means that it does only work with OpenSSL 0.9.6 and NOT in 0.9.7 where it causes a program that uses the function to crash. It could use the API function X509_get_ext_d2i(). {141} Example 5-10, line 30/39; The for loop will just loop forever, so line 40 will never be reached - leaving a dangling thread. Could change it to a do loop as in example 5.6. [145] 2nd paragraph; The book says "Of these two choices, DH is better because temporary RSA keys violate the SSL/TLS protocols". While it is true that ephemeral Diffie-Hellman is better than ephemeral RSA from a security perspective, it is definitely not true that temporary RSA keys violate the SSL/TLS protocols. Pages 39 and 40 of RFC 2246 describe the (legitimate) use of ephemeral RSA in the TLS protocol. Pages 25 and 26 of the SSLv3 draft (draft-freier-ssl-version3-02.txt) describe the use of ephemeral RSA in the SSLv3 protocol. {164} 3rd paragraph; The second sentence in the 3rd paragraph references a non-implemented funciton called set_nonblocking. The function is actually written (in the example code on page 160) as set_non-blocking. {165}3rd paragraph, 3rd sentence; "They assert we are not in the middle of a read operation..." should read "They assert we are not in the middle of a write operation..." (185) Example 6-3; The coding is not working as the description on the same page. There are problems in the 3rd parameters of 2 EVP_EncryptUpdate. data[ol] should be changed as the following for (i = 0; i < inl / 100; i++) { EVP_EncryptUpdate (ctx, &ret[ol], &tmp, &data[i*100], 100); ol += tmp; } if (inl % 100) { EVP_EncryptUpdate (ctx, &ret[ol], &tmp, &data[(inl/100)*100], inl % 100); ol += tmp; } [187] Example 66; The code calls EVP_EncryptInit() and EVP_DecryptInit(), which (in OpenSSL v0.9.7 at least) end up calling EVP_CipherInit_Ex(), which has a line: crypto/evp/evp_env.c#146: ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size); this malloc'd space seems not to be freed except in EVP_CIPHER_CTX_cleanup() which your example code does not call -- if this is indeed a problem (as I believe it is), it may be more widespread. It shows up in a library I am using (PTPTL at SourceForge.net), as well. Counterexamples (of cleaning up afterwards by calling EVP_CIPHER_CTX_cleanup()) can be found, e.g., in cypto\evp\evp_test.c in test1(), and in crypto\pem\pem_lib.c in PEM_ASN1_write_bio(). In your particular example, of course, the program exits immediately so it's not a "serious technical mistake" in that sense. However in the pedagogic sense, I think it is a serious omission: we look to excellent books like this for good code examples, and this leak is fairly difficult to detect. [195] 1st line, continued paragraph from previous page; Sentence: The MAC algorithm produces a hash value from the data to protect a secret key. Maybe should be: The MAC algorithm produces a hash value from the data to protect and the secret key. {208} In the section of XCBC-MAC; I'm not reporting errors for XCBC-MAC but would like to give suggestions. It would be better and more practical if the code shown in this section could comply the functions specified in RFC 3566. {283} In the main() of example 10-5; The certificate request generated with the sample code will NOT work correctly with some certificate authorities (for example Verisign). The problem is that the code fails to set the version number. The following line of code should be added after creating the request (with X509_REQ_new()): X509_REQ_set_version(req, 0L); {295}last code example, last line; fprintf(stderr, "Error reading the CRL file\n"); should read fprintf(stderr, "Error reading the CA directory\n"); [310] Description of CA command; Version 0.9.7b lists a "-extfile file - Configuration file with X509v3 extentions to add" option that is not described in the book. {Chapter 10} Example 10-6. Creating a certificate from a request and CA credentials ; (I use Safari online, so page numbers do not match printed editions.) The string "nonrepudiation" in the ext_ent array entry for keyUsage fails on OpenSSL 0.9.8e because OpenSSL uses strcmp, looking for an exact case match. When I change nonrepudiation to be mixed case, nonRepudiation, example 10-6 works correctly since the strcmp detects a match. Without this, OpenSSL reports an extension usage error. I'm guessing an older version of OpenSSL either used stricmp, or perhaps it had all lowercase "nonrepudiation." I hope this helps. Thanks for an informative book!