SlideShare una empresa de Scribd logo
1 de 7
Descargar para leer sin conexión
A	few	words	about	OpenSSL
Author: Andrey Karpov
Date: 17.12.2012
This is a small note on the results of checking the OpenSSL project with the PVS-Studio analyzer. I analyzed
the openssl-0.9.8-stable-SNAP-20121208 version.
On checking OpenSSL
I have recently written the post "Security, security! But do you test it?" about checking the TOR project. I
mentioned the OpenSSL library together with it, as it is used in the TOR project.
The article provoked active discussions on some programmer resources. Programmers appear to be very
much concerned about the quality of the OpenSSL library. But I wasn't able to answer some questions
regarding the library. I was also reproached for not having informed the OpenSSL developers about all the
unsafe fragments.
So I'd like to comment on this. You see, I didn't plan to check the OpenSSL library and study the results of its
analysis when being involved in analyzing TOR. This library just happened to be around. The TOR project
included some version of OpenSSL, that's why it was checked by the PVS-Studio analyzer along with the
main project.
Then I decided to improve the situation and downloaded and checked the latest version of the OpenSSL
library.
To be honest, there's not much to tell. Almost nothing strange was found. Those errors described in that
earlier article are fixed by now. OpenSSL is a quality project; the library has been already checked by many
tools (Clang, Cppcheck, Coverity, DoubleCheck, Coccinelle, Klocwork, etc.). So, the library is cleaned out. It
would be a feat to find even one error there.
Ok, I will tell you about some suspicious things I've found in the code of the OpenSSL library. They are most
likely just insignificant slip-ups rather than serious errors. But I have to write at least something, right? :)
Strange fragment N1
EVP_PKEY *STORE_get_private_key(....)
{
STORE_OBJECT *object;
....
if (!object || !object->data.key || !object->data.key)
{
STOREerr(STORE_F_STORE_GET_PRIVATE_KEY,
STORE_R_FAILED_GETTING_KEY);
return 0;
}
....
}
PVS-Studio's diagnostic message: V501 There are identical sub-expressions '!object->data.key' to the left
and to the right of the '||' operator. str_lib.c 475
The "!object->data.key" condition is repeated twice. The second check must be just odd, and there's
nothing dangerous about it. But if it turns out that the programmer wanted to check another class member,
this is certainly a trouble.
This strange check can be seen in three other fragments of the str_lib.c file (seems like Copy-Paste):
• V501 There are identical sub-expressions '!object->data.key' to the left and to the right of the '||'
operator. str_lib.c 616
• V501 There are identical sub-expressions '!object->data.key' to the left and to the right of the '||'
operator. str_lib.c 670
• V501 There are identical sub-expressions '!object->data.key' to the left and to the right of the '||'
operator. str_lib.c 811
Strange fragment N2
There are several fragments where the pointer is first used and then checked for being a null pointer. But
only one fragment looks really strange to me:
int OBJ_obj2txt(char *buf, int buf_len,
const ASN1_OBJECT *a, int no_name)
{
....
if ((a == NULL) || (a->data == NULL)) {
buf[0]='0';
return(0);
}
....
if (buf)
....
}
PVS-Studio's diagnostic message: V595 The 'buf' pointer was utilized before it was verified against nullptr.
Check lines: 448, 461. obj_dat.c 448
It is first checked that 'a' or 'a->data' equal zero. If it is so, the 'buf' pointer is used. But the 'buf' pointer
itself may equal zero too. The check "if (buf)" a bit farther in the code hints at that.
Strange fragment N3
The PVS-Studio analyzer seems to have found a true error in the following code fragment.
int ssl3_get_cert_verify(SSL *s)
{
int type=0,i,j;
....
if ((peer != NULL) && (type | EVP_PKT_SIGN))
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
SSL_R_MISSING_VERIFY_MESSAGE);
goto f_err;
}
....
}
PVS-Studio's diagnostic message: V617 Consider inspecting the condition. The '0x0010' argument of the '|'
bitwise operation contains a non-zero value. s3_srvr.c 2394
The expression "(type | EVP_PKT_SIGN)" is always true. Perhaps the following code should be written here:
"type & EVP_PKT_SIGN".
Strange fragment N4
There are several senseless checks like the following one:
int MAIN(int argc, char **argv)
{
....
long dsa_c[DSA_NUM][2];
....
if (dsa_c[i] == 0)
{
dsa_c[i][0]=1;
dsa_c[i][1]=1;
}
....
}
PVS-Studio's diagnostic message: V600 Consider inspecting the condition. The 'dsa_c[i]' pointer is always
not equal to NULL. speed.c 1486
'dsa_c' here is a two-dimensional array. That's why the expression "dsa_c[i] == 0" is always true and
therefore meaningless. There is a code fragment nearby:
if (rsa_c[i][0] == 0)
{
rsa_c[i][0]=1;
rsa_c[i][1]=20;
}
Maybe the 'dsa_c' array should be handled in the same way. In this case the code should look like this:
if (dsa_c[i][0] == 0)
{
dsa_c[i][0]=1;
dsa_c[i][1]=1;
}
This strange check can be found in several other fragments:
• V600 Consider inspecting the condition. The 'ecdsa_c[i]' pointer is always not equal to NULL.
speed.c 1506
• V600 Consider inspecting the condition. The 'ecdsa_c[i]' pointer is always not equal to NULL.
speed.c 1523
• V600 Consider inspecting the condition. The 'ecdsa_c[i]' pointer is always not equal to NULL.
speed.c 1540
• V600 Consider inspecting the condition. The 'ecdh_c[i]' pointer is always not equal to NULL. speed.c
1560
• V600 Consider inspecting the condition. The 'ecdh_c[i]' pointer is always not equal to NULL. speed.c
1577
• V600 Consider inspecting the condition. The 'ecdh_c[i]' pointer is always not equal to NULL. speed.c
1594
Non-ambiguous fragments
There are a few small slip-ups. They are definitely not errors - just excessive code. Here's an example of
excessive code in a condition:
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
{
int c;
....
c= *(s++);
if (!( ((c >= 'a') && (c <= 'z')) ||
((c >= 'A') && (c <= 'Z')) ||
(c == ' ') || <<<---
((c >= '0') && (c <= '9')) ||
(c == ' ') || (c == ''') || <<<---
(c == '(') || (c == ')') ||
(c == '+') || (c == ',') ||
(c == '-') || (c == '.') ||
(c == '/') || (c == ':') ||
(c == '=') || (c == '?')))
ia5=1;
....
}
PVS-Studio's diagnostic message: V501 There are identical sub-expressions '(c == ' ')' to the left and to the
right of the '||' operator. a_print.c 76
The check that the character is a space is repeated twice: the programmer wrote it just from inattention.
Nothing dangerous. I saw a couple of such things in other fragments, but they are not interesting to
mention.
The last thing worth mentioning
The following thing I found difficult to figure out: in some fragments, the analyzer had detected a
conversion of a memsize-type to a 32-bit type and then back to memsize. This is one of these places:
int ec_GFp_simple_points_make_affine(const EC_GROUP *group,
size_t num, EC_POINT *points[], BN_CTX *ctx)
{
BIGNUM **heap = NULL;
size_t pow2 = 0;
....
heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
....
}
PVS-Studio's diagnostic message: V220 Suspicious sequence of types castings: memsize -> 32-bit integer ->
memsize. The value being casted: 'pow2'. ecp_smpl.c 1576
It appears that the OPENSSL_malloc macro is poorly written.
void *CRYPTO_malloc(int num, const char *file, int line);
#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__)
As a result, we get the following code after preprocessing:
heap = CRYPTO_malloc ((int)pow2 * sizeof heap[0], __FILE__,__LINE__);
This leads to crazy type conversions. The 'pow2' variable of the size_t type is explicitly cast to the 'int' type
at first. Then, after being multiplied by 'sizeof()', the expression's type changes to size_t again. After that it is
again cast to the 'int' type when calling the CRYPTO_malloc() function, the conversion being implicit this
time.
Well, this type conversion is absolutely meaningless - just an occasion to make a mistake. For instance, one
might write something like this:
int *p1, *p2;
int x, y;
....
p = OPENSSL_malloc(p1 == p2 ? x : y);
The 'p1' pointer will lose the high-order bits on a 64-bit system, and the comparison result will be incorrect.
This is of course an artificial example, but one still shouldn't create macros like this. It should be at least
rewritten in the following way:
#define OPENSSL_malloc(num) CRYPTO_malloc((int)(num),__FILE__,__LINE__)
The best thing, however, is not to use the 'int' type here at all. The allocated memory size should be passed
in a memsize-type variable. For example, 'size_t'.
Conclusion
Thank you all for your attention. I will be glad if this note helps to somehow improve the OpenSSL library. As
usually, I recommend that the library's authors don't stop at the strange fragments mentioned here but
check the library once again and study the report themselves. We provide developers of open-source
libraries with a free registration key for some time. Perhaps you will notice some dangerous fragments I
disregarded.

Más contenido relacionado

La actualidad más candente

La actualidad más candente (19)

Checking the Open-Source Multi Theft Auto Game
Checking the Open-Source Multi Theft Auto GameChecking the Open-Source Multi Theft Auto Game
Checking the Open-Source Multi Theft Auto Game
 
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ..."Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
 
A fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBoxA fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBox
 
The Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmThe Unicorn's Travel to the Microcosm
The Unicorn's Travel to the Microcosm
 
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source CodeA Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
Rechecking Apache HTTP Server
Rechecking Apache HTTP ServerRechecking Apache HTTP Server
Rechecking Apache HTTP Server
 
Asterisk: PVS-Studio Takes Up Telephony
Asterisk: PVS-Studio Takes Up TelephonyAsterisk: PVS-Studio Takes Up Telephony
Asterisk: PVS-Studio Takes Up Telephony
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
 
Lab
LabLab
Lab
 
Checking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-StudioChecking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-Studio
 
The Last Line Effect
The Last Line EffectThe Last Line Effect
The Last Line Effect
 
C++ boot camp part 1/2
C++ boot camp part 1/2C++ boot camp part 1/2
C++ boot camp part 1/2
 
Reanalyzing the Notepad++ project
Reanalyzing the Notepad++ projectReanalyzing the Notepad++ project
Reanalyzing the Notepad++ project
 
Checking Intel IPP Samples for Windows - Continuation
Checking Intel IPP Samples for Windows - ContinuationChecking Intel IPP Samples for Windows - Continuation
Checking Intel IPP Samples for Windows - Continuation
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
Source code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checkedSource code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checked
 

Destacado

Destacado (8)

50 Essential Content Marketing Hacks (Content Marketing World)
50 Essential Content Marketing Hacks (Content Marketing World)50 Essential Content Marketing Hacks (Content Marketing World)
50 Essential Content Marketing Hacks (Content Marketing World)
 
Prototyping is an attitude
Prototyping is an attitudePrototyping is an attitude
Prototyping is an attitude
 
10 Insightful Quotes On Designing A Better Customer Experience
10 Insightful Quotes On Designing A Better Customer Experience10 Insightful Quotes On Designing A Better Customer Experience
10 Insightful Quotes On Designing A Better Customer Experience
 
Learn BEM: CSS Naming Convention
Learn BEM: CSS Naming ConventionLearn BEM: CSS Naming Convention
Learn BEM: CSS Naming Convention
 
How to Build a Dynamic Social Media Plan
How to Build a Dynamic Social Media PlanHow to Build a Dynamic Social Media Plan
How to Build a Dynamic Social Media Plan
 
SEO: Getting Personal
SEO: Getting PersonalSEO: Getting Personal
SEO: Getting Personal
 
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika AldabaLightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
 
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job? Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
 

Similar a A few words about OpenSSL

Similar a A few words about OpenSSL (20)

Analysis of Godot Engine's Source Code
Analysis of Godot Engine's Source CodeAnalysis of Godot Engine's Source Code
Analysis of Godot Engine's Source Code
 
How to make fewer errors at the stage of code writing. Part N4.
How to make fewer errors at the stage of code writing. Part N4.How to make fewer errors at the stage of code writing. Part N4.
How to make fewer errors at the stage of code writing. Part N4.
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
Checking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerChecking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzer
 
LibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-StudioLibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-Studio
 
Miranda NG Project to Get the "Wild Pointers" Award (Part 1)
Miranda NG Project to Get the "Wild Pointers" Award (Part 1) Miranda NG Project to Get the "Wild Pointers" Award (Part 1)
Miranda NG Project to Get the "Wild Pointers" Award (Part 1)
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large report
 
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindAccord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
 
Checking WinMerge with PVS-Studio for the second time
Checking WinMerge with PVS-Studio for the second timeChecking WinMerge with PVS-Studio for the second time
Checking WinMerge with PVS-Studio for the second time
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition Software
 
Checking VirtualDub
Checking VirtualDubChecking VirtualDub
Checking VirtualDub
 
Analysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) projectAnalysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) project
 
Analyzing Firebird 3.0
Analyzing Firebird 3.0Analyzing Firebird 3.0
Analyzing Firebird 3.0
 
A Spin-off: Firebird Checked by PVS-Studio
A Spin-off: Firebird Checked by PVS-StudioA Spin-off: Firebird Checked by PVS-Studio
A Spin-off: Firebird Checked by PVS-Studio
 
PVS-Studio for Linux Went on a Tour Around Disney
PVS-Studio for Linux Went on a Tour Around DisneyPVS-Studio for Linux Went on a Tour Around Disney
PVS-Studio for Linux Went on a Tour Around Disney
 
A Boring Article About a Check of the OpenSSL Project
A Boring Article About a Check of the OpenSSL ProjectA Boring Article About a Check of the OpenSSL Project
A Boring Article About a Check of the OpenSSL Project
 
PVS-Studio vs Chromium - Continuation
PVS-Studio vs Chromium - ContinuationPVS-Studio vs Chromium - Continuation
PVS-Studio vs Chromium - Continuation
 
PVS-Studio vs Clang
PVS-Studio vs ClangPVS-Studio vs Clang
PVS-Studio vs Clang
 
Mathematicians: Trust, but Verify
Mathematicians: Trust, but VerifyMathematicians: Trust, but Verify
Mathematicians: Trust, but Verify
 

Último

Último (20)

Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 

A few words about OpenSSL

  • 1. A few words about OpenSSL Author: Andrey Karpov Date: 17.12.2012 This is a small note on the results of checking the OpenSSL project with the PVS-Studio analyzer. I analyzed the openssl-0.9.8-stable-SNAP-20121208 version. On checking OpenSSL I have recently written the post "Security, security! But do you test it?" about checking the TOR project. I mentioned the OpenSSL library together with it, as it is used in the TOR project. The article provoked active discussions on some programmer resources. Programmers appear to be very much concerned about the quality of the OpenSSL library. But I wasn't able to answer some questions regarding the library. I was also reproached for not having informed the OpenSSL developers about all the unsafe fragments. So I'd like to comment on this. You see, I didn't plan to check the OpenSSL library and study the results of its analysis when being involved in analyzing TOR. This library just happened to be around. The TOR project included some version of OpenSSL, that's why it was checked by the PVS-Studio analyzer along with the main project. Then I decided to improve the situation and downloaded and checked the latest version of the OpenSSL library. To be honest, there's not much to tell. Almost nothing strange was found. Those errors described in that earlier article are fixed by now. OpenSSL is a quality project; the library has been already checked by many tools (Clang, Cppcheck, Coverity, DoubleCheck, Coccinelle, Klocwork, etc.). So, the library is cleaned out. It would be a feat to find even one error there. Ok, I will tell you about some suspicious things I've found in the code of the OpenSSL library. They are most likely just insignificant slip-ups rather than serious errors. But I have to write at least something, right? :) Strange fragment N1 EVP_PKEY *STORE_get_private_key(....) { STORE_OBJECT *object; .... if (!object || !object->data.key || !object->data.key)
  • 2. { STOREerr(STORE_F_STORE_GET_PRIVATE_KEY, STORE_R_FAILED_GETTING_KEY); return 0; } .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions '!object->data.key' to the left and to the right of the '||' operator. str_lib.c 475 The "!object->data.key" condition is repeated twice. The second check must be just odd, and there's nothing dangerous about it. But if it turns out that the programmer wanted to check another class member, this is certainly a trouble. This strange check can be seen in three other fragments of the str_lib.c file (seems like Copy-Paste): • V501 There are identical sub-expressions '!object->data.key' to the left and to the right of the '||' operator. str_lib.c 616 • V501 There are identical sub-expressions '!object->data.key' to the left and to the right of the '||' operator. str_lib.c 670 • V501 There are identical sub-expressions '!object->data.key' to the left and to the right of the '||' operator. str_lib.c 811 Strange fragment N2 There are several fragments where the pointer is first used and then checked for being a null pointer. But only one fragment looks really strange to me: int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) { .... if ((a == NULL) || (a->data == NULL)) { buf[0]='0'; return(0); } ....
  • 3. if (buf) .... } PVS-Studio's diagnostic message: V595 The 'buf' pointer was utilized before it was verified against nullptr. Check lines: 448, 461. obj_dat.c 448 It is first checked that 'a' or 'a->data' equal zero. If it is so, the 'buf' pointer is used. But the 'buf' pointer itself may equal zero too. The check "if (buf)" a bit farther in the code hints at that. Strange fragment N3 The PVS-Studio analyzer seems to have found a true error in the following code fragment. int ssl3_get_cert_verify(SSL *s) { int type=0,i,j; .... if ((peer != NULL) && (type | EVP_PKT_SIGN)) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_MISSING_VERIFY_MESSAGE); goto f_err; } .... } PVS-Studio's diagnostic message: V617 Consider inspecting the condition. The '0x0010' argument of the '|' bitwise operation contains a non-zero value. s3_srvr.c 2394 The expression "(type | EVP_PKT_SIGN)" is always true. Perhaps the following code should be written here: "type & EVP_PKT_SIGN". Strange fragment N4 There are several senseless checks like the following one:
  • 4. int MAIN(int argc, char **argv) { .... long dsa_c[DSA_NUM][2]; .... if (dsa_c[i] == 0) { dsa_c[i][0]=1; dsa_c[i][1]=1; } .... } PVS-Studio's diagnostic message: V600 Consider inspecting the condition. The 'dsa_c[i]' pointer is always not equal to NULL. speed.c 1486 'dsa_c' here is a two-dimensional array. That's why the expression "dsa_c[i] == 0" is always true and therefore meaningless. There is a code fragment nearby: if (rsa_c[i][0] == 0) { rsa_c[i][0]=1; rsa_c[i][1]=20; } Maybe the 'dsa_c' array should be handled in the same way. In this case the code should look like this: if (dsa_c[i][0] == 0) { dsa_c[i][0]=1; dsa_c[i][1]=1; }
  • 5. This strange check can be found in several other fragments: • V600 Consider inspecting the condition. The 'ecdsa_c[i]' pointer is always not equal to NULL. speed.c 1506 • V600 Consider inspecting the condition. The 'ecdsa_c[i]' pointer is always not equal to NULL. speed.c 1523 • V600 Consider inspecting the condition. The 'ecdsa_c[i]' pointer is always not equal to NULL. speed.c 1540 • V600 Consider inspecting the condition. The 'ecdh_c[i]' pointer is always not equal to NULL. speed.c 1560 • V600 Consider inspecting the condition. The 'ecdh_c[i]' pointer is always not equal to NULL. speed.c 1577 • V600 Consider inspecting the condition. The 'ecdh_c[i]' pointer is always not equal to NULL. speed.c 1594 Non-ambiguous fragments There are a few small slip-ups. They are definitely not errors - just excessive code. Here's an example of excessive code in a condition: int ASN1_PRINTABLE_type(const unsigned char *s, int len) { int c; .... c= *(s++); if (!( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || (c == ' ') || <<<--- ((c >= '0') && (c <= '9')) || (c == ' ') || (c == ''') || <<<--- (c == '(') || (c == ')') || (c == '+') || (c == ',') || (c == '-') || (c == '.') || (c == '/') || (c == ':') || (c == '=') || (c == '?'))) ia5=1;
  • 6. .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions '(c == ' ')' to the left and to the right of the '||' operator. a_print.c 76 The check that the character is a space is repeated twice: the programmer wrote it just from inattention. Nothing dangerous. I saw a couple of such things in other fragments, but they are not interesting to mention. The last thing worth mentioning The following thing I found difficult to figure out: in some fragments, the analyzer had detected a conversion of a memsize-type to a 32-bit type and then back to memsize. This is one of these places: int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) { BIGNUM **heap = NULL; size_t pow2 = 0; .... heap = OPENSSL_malloc(pow2 * sizeof heap[0]); .... } PVS-Studio's diagnostic message: V220 Suspicious sequence of types castings: memsize -> 32-bit integer -> memsize. The value being casted: 'pow2'. ecp_smpl.c 1576 It appears that the OPENSSL_malloc macro is poorly written. void *CRYPTO_malloc(int num, const char *file, int line); #define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__) As a result, we get the following code after preprocessing: heap = CRYPTO_malloc ((int)pow2 * sizeof heap[0], __FILE__,__LINE__); This leads to crazy type conversions. The 'pow2' variable of the size_t type is explicitly cast to the 'int' type at first. Then, after being multiplied by 'sizeof()', the expression's type changes to size_t again. After that it is again cast to the 'int' type when calling the CRYPTO_malloc() function, the conversion being implicit this time.
  • 7. Well, this type conversion is absolutely meaningless - just an occasion to make a mistake. For instance, one might write something like this: int *p1, *p2; int x, y; .... p = OPENSSL_malloc(p1 == p2 ? x : y); The 'p1' pointer will lose the high-order bits on a 64-bit system, and the comparison result will be incorrect. This is of course an artificial example, but one still shouldn't create macros like this. It should be at least rewritten in the following way: #define OPENSSL_malloc(num) CRYPTO_malloc((int)(num),__FILE__,__LINE__) The best thing, however, is not to use the 'int' type here at all. The allocated memory size should be passed in a memsize-type variable. For example, 'size_t'. Conclusion Thank you all for your attention. I will be glad if this note helps to somehow improve the OpenSSL library. As usually, I recommend that the library's authors don't stop at the strange fragments mentioned here but check the library once again and study the report themselves. We provide developers of open-source libraries with a free registration key for some time. Perhaps you will notice some dangerous fragments I disregarded.