Repository: nginx/nginx
File: src/event/ngx_event_openssl.c (C)

Code before:
        rv = NGX_OK;
    BIO_free_all(in);
    return rv;
}
#endif /* NGX_ECH */


ngx_int_t
ngx_ssl_echfiles(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *filenames)
{
#ifdef NGX_ECH
    int             somekeyworked, numkeys, for_retry;
    void           *genechstore;
    ngx_int_t       rv;
    ngx_str_t      *filename;
    ngx_uint_t      i;
    OSSL_ECHSTORE  *es;

    if (!filenames) {
        return NGX_OK;
    }

    es = OSSL_ECHSTORE_new(NULL, NULL);
    if (es == NULL) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "ngx_ssl_echfiles, error allocating store" );
        return NGX_ERROR;
    }
    rv = NGX_ERROR;
    genechstore = (void *)es;
    somekeyworked = 0;
    numkeys = 0;

    /* process each ssl_echfile directive file name */
    filename = filenames->elts;
    /* mark the first named file(s) as being for re-try */
    for_retry = OSSL_ECH_FOR_RETRY;
    for (i = 0; i < filenames->nelts; i++, filename++) {
        if (filename->len == 0) {
            continue;
        }
        if (ngx_conf_full_name(cf->cycle, filename, 1) != NGX_OK) {
            goto cleanup;
        }

        if (ngx_ssl_load_one_echkey(ssl, filename, genechstore,
                                    for_retry) != NGX_OK) {
            ngx_ssl_error(NGX_LOG_ALERT, ssl->log, 0,
                          "ngx_ssl_echfiles, failed for: %s",
                          filename->data);
            goto cleanup;

Review comment (bug):
You can look across this file for the right way to report an SSL function error. A good example is this:
```
    store = SSL_CTX_get_cert_store(ssl->ctx);                                    
                                                                                 
    if (store == NULL) {                                                         
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,                                
                      "SSL_CTX_get_cert_store() failed");                        
        return NGX_ERROR;                                                        
    } 
```

Fort this case:
```
es = OSSL_ECHSTORE_new(NULL, NULL);
if (es == NULL) {
    ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "OSSL_ECHSTORE_new() failed");
    return NGX_ERROR;
}
```

This relates to other SSL calls errors as well.

Code after:
    rc = NGX_ERROR;
    filename = filenames->elts;

    for (i = 0; i < filenames->nelts; i++) {

        if (ngx_conf_full_name(cf->cycle, &filename[i], 1) != NGX_OK) {
            goto cleanup;
        }

        in = BIO_new_file((char *) filename[i].data, "r");
        if (in == NULL) {
            ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                          "BIO_new_file(\"%s\") failed", filename[i].data);
            goto cleanup;
        }

        /*
         * We only set the ECHConfigList from the first file read to use
         * in ECH retry-configs.
         *
         * That allows many sensible key rotation schemes so that the
         * values sent in ECH retry-configs are smaller and current.
         * For example, if the first file name has the current ECH
         * private key, and a second one has the previously used key
         * that some clients may still use due to DNS caching.
         */

         if (OSSL_ECHSTORE_read_pem(es, in, i ? OSSL_ECH_NO_RETRY
                                              : OSSL_ECH_FOR_RETRY)
             != 1)
         {
             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                           "OSSL_ECHSTORE_read_pem(%s) failed",
                           filename[i].data);
             BIO_free(in);
             goto cleanup;
         }

         BIO_free(in);
    }

    /*
     * load the ECH store after checking there's at least one ECH
     * private key in there (the PEM file spec allows zero or one
     * private key per file)
     */

    if (OSSL_ECHSTORE_num_keys(es, &numkeys) != 1) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "OSSL_ECHSTORE_num_keys(%s) failed");
        goto cleanup;