Alexey Serbin has posted comments on this change.

Change subject: [util/crypto] certificate management (part 1)
......................................................................


Patch Set 6:

(16 comments)

Thank you for the review.  I'll post new version shortly.

http://gerrit.cloudera.org:8080/#/c/4799/6/src/kudu/security/crypto/cert_management.cc
File src/kudu/security/crypto/cert_management.cc:

Line 78:       const_cast<char*>("critical,digitalSignature,keyEncipherment")));
> Please briefly document what each of these does.
Done


Line 98:     uni_ptr<RSA> rsa(RSA_generate_key(num_bits, RSA_F4, nullptr, 
nullptr),
> This method is deprecated and replaced with RSA_generate_key_ex.  If there'
Done


Line 100:     CERT_RET_NOT_OK(EVP_PKEY_assign_RSA(key.get(), rsa.get()),
> Could you doc the reason behind assign as opposed to set1?  The ownership h
Good observation.

The main reason what that I saw that pattern in one of OpenSSL apps :)  Also, 
it makes sense to transfer ownership to the parent key: calling lesser number 
of RSA_free() functions for the success path.

BTW, EVP_PKEY_set1_RSA is just a wrapper around EVP_PKEY_assign_RSA:

int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
{
    int ret = EVP_PKEY_assign_RSA(pkey, key);
    if (ret)
        RSA_up_ref(key);
    return ret;
}

So, in case of a failure in both cases we need to make sure there is no 
double-free.  I took a look at the code: in case of failure the RSA key needs 
to be freed (i.e. when EVP_PKEY_set_type() failed, the key is not set to the 
parent key):

int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
    if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
        return 0;
    pkey->pkey.ptr = key;
    return (key != NULL);
}


Line 104:   if (ret) {
> Maybe this should just be a CHECK_NOTNULL at the start?  Seems like a bug t
It's used with nullptr in tests, so CHECK_NOTNULL is not needed.  Do you think 
having such a convention is too bizarre?


Line 146:   if (ret) {
> same here with CHECK_NOTNULL
same here -- it's used in tests with nullptr argument just to make sure it does 
not return an error, but if you think it's a bizarre convention, I can change 
it.


Line 203:   RETURN_NOT_OK(DoCertify(EVP_sha256(), req.expiration_sec(), 0, 
x509.get()));
> Do we check that the request specifies SHA256?
Nope, but that's implied -- but it's a good idea to add it for better 
protection against different versions of client/server in the field.

But in general, do we want to check and bail with an error in case of mismatch 
or we want to support other digests here as well?


PS6, Line 260: rc < 0
> != 1, and remove the if below
There was a special provision to distinguish between different types of errors: 
mismatch and some other errors.  Why do you think it's not worth it?


PS6, Line 261: Cert
> Should this be CSR instead of Cert?
Done


Line 268:   pub_key.release();
> Pretty sure this is a memory leak: "X509_set_pubkey() attempts to set the p
Good catch -- yes, this is a mistake.  Somehow I confused it with and read docs 
for the X509_PUBKEY_set0_param() API call instead.


PS6, Line 272: pkey
> Is this a public or private key?
Private -- the signer takes private key to make a signature.  That pkey notion 
came from openssl sources, and yes, it's confusing.  I'll update the name of 
the parameter for clarity.


PS6, Line 315: utilty
> utility
Done


PS6, Line 326: EVP_PKEY_copy_parameters(pub_key.get(), ca_private_key_.get());
> ???
This is what it is: you can see it in apps/ca.c, line 2096.  

It copies missing public key parameters (if any is missing) from CA key into 
the request public key, as from the documentation:

"The main purpose of the functions EVP_PKEY_missing_parameters() and 
EVP_PKEY_copy_parameters() is to handle public keys in certificates where the 
parameters are sometimes omitted from a public key if they are inherited from 
the CA that signed it."

I included this code as is, just adapted it.  Probably, we can drop this part 
at all with no harm -- let's do that for sanity.


Line 343:   if (clrext != 0) {
> What is this doing?  It seems we always call this with clrext == 0.
I kept it thinking that we might need those extensions.  De facto they are not 
used -- that's correct.  I'll remove that.


http://gerrit.cloudera.org:8080/#/c/4799/6/src/kudu/security/crypto/cert_management.h
File src/kudu/security/crypto/cert_management.h:

Line 118:   Status GenerateRequest(const CertSubjectInfo& info, const Key& key,
> After calling this, the key must outlive the req, right?  May want to doc t
RIght -- the key is needed for future use is using the generated certificate.


PS6, Line 149: Certify
> I think this should be called 'Sign'.  'Certify' could be confused with val
Done


http://gerrit.cloudera.org:8080/#/c/4799/6/src/kudu/security/crypto/crypto_engine.h
File src/kudu/security/crypto/crypto_engine.h:

Line 28: typedef struct bio_st BIO;
> I think this is already defined in crypto_common.h
Done


-- 
To view, visit http://gerrit.cloudera.org:8080/4799
To unsubscribe, visit http://gerrit.cloudera.org:8080/settings

Gerrit-MessageType: comment
Gerrit-Change-Id: I69c1da97e6d013a034aefda59988b593ae1d6304
Gerrit-PatchSet: 6
Gerrit-Project: kudu
Gerrit-Branch: master
Gerrit-Owner: Alexey Serbin <aser...@cloudera.com>
Gerrit-Reviewer: Adar Dembo <a...@cloudera.com>
Gerrit-Reviewer: Alexey Serbin <aser...@cloudera.com>
Gerrit-Reviewer: Dan Burkert <danburk...@apache.org>
Gerrit-Reviewer: Kudu Jenkins
Gerrit-Reviewer: Tidy Bot
Gerrit-Reviewer: Todd Lipcon <t...@apache.org>
Gerrit-HasComments: Yes

Reply via email to