LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/engine - eng_ctrl.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 121 0.0 %
Date: 2015-10-10 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /* crypto/engine/eng_ctrl.c */
       2             : /* ====================================================================
       3             :  * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
       4             :  *
       5             :  * Redistribution and use in source and binary forms, with or without
       6             :  * modification, are permitted provided that the following conditions
       7             :  * are met:
       8             :  *
       9             :  * 1. Redistributions of source code must retain the above copyright
      10             :  *    notice, this list of conditions and the following disclaimer.
      11             :  *
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in
      14             :  *    the documentation and/or other materials provided with the
      15             :  *    distribution.
      16             :  *
      17             :  * 3. All advertising materials mentioning features or use of this
      18             :  *    software must display the following acknowledgment:
      19             :  *    "This product includes software developed by the OpenSSL Project
      20             :  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
      21             :  *
      22             :  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
      23             :  *    endorse or promote products derived from this software without
      24             :  *    prior written permission. For written permission, please contact
      25             :  *    licensing@OpenSSL.org.
      26             :  *
      27             :  * 5. Products derived from this software may not be called "OpenSSL"
      28             :  *    nor may "OpenSSL" appear in their names without prior written
      29             :  *    permission of the OpenSSL Project.
      30             :  *
      31             :  * 6. Redistributions of any form whatsoever must retain the following
      32             :  *    acknowledgment:
      33             :  *    "This product includes software developed by the OpenSSL Project
      34             :  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
      35             :  *
      36             :  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
      37             :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      38             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      39             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
      40             :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      41             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      42             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      43             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      44             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      45             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      46             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      47             :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      48             :  * ====================================================================
      49             :  *
      50             :  * This product includes cryptographic software written by Eric Young
      51             :  * (eay@cryptsoft.com).  This product includes software written by Tim
      52             :  * Hudson (tjh@cryptsoft.com).
      53             :  *
      54             :  */
      55             : 
      56             : #include "eng_int.h"
      57             : 
      58             : /*
      59             :  * When querying a ENGINE-specific control command's 'description', this
      60             :  * string is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL.
      61             :  */
      62             : static const char *int_no_description = "";
      63             : 
      64             : /*
      65             :  * These internal functions handle 'CMD'-related control commands when the
      66             :  * ENGINE in question has asked us to take care of it (ie. the ENGINE did not
      67             :  * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag.
      68             :  */
      69             : 
      70             : static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN *defn)
      71             : {
      72           0 :     if ((defn->cmd_num == 0) || (defn->cmd_name == NULL))
      73             :         return 1;
      74             :     return 0;
      75             : }
      76             : 
      77           0 : static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN *defn, const char *s)
      78             : {
      79             :     int idx = 0;
      80           0 :     while (!int_ctrl_cmd_is_null(defn) && (strcmp(defn->cmd_name, s) != 0)) {
      81           0 :         idx++;
      82           0 :         defn++;
      83             :     }
      84           0 :     if (int_ctrl_cmd_is_null(defn))
      85             :         /* The given name wasn't found */
      86             :         return -1;
      87           0 :     return idx;
      88             : }
      89             : 
      90           0 : static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num)
      91             : {
      92             :     int idx = 0;
      93             :     /*
      94             :      * NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So
      95             :      * our searches don't need to take any longer than necessary.
      96             :      */
      97           0 :     while (!int_ctrl_cmd_is_null(defn) && (defn->cmd_num < num)) {
      98           0 :         idx++;
      99           0 :         defn++;
     100             :     }
     101           0 :     if (defn->cmd_num == num)
     102             :         return idx;
     103             :     /* The given cmd_num wasn't found */
     104             :     return -1;
     105             : }
     106             : 
     107           0 : static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p,
     108             :                            void (*f) (void))
     109             : {
     110             :     int idx;
     111             :     char *s = (char *)p;
     112             :     /* Take care of the easy one first (eg. it requires no searches) */
     113           0 :     if (cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE) {
     114           0 :         if ((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns))
     115             :             return 0;
     116           0 :         return e->cmd_defns->cmd_num;
     117             :     }
     118             :     /* One or two commands require that "p" be a valid string buffer */
     119           0 :     if ((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) ||
     120           0 :         (cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) ||
     121             :         (cmd == ENGINE_CTRL_GET_DESC_FROM_CMD)) {
     122           0 :         if (s == NULL) {
     123           0 :             ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ERR_R_PASSED_NULL_PARAMETER);
     124             :             return -1;
     125             :         }
     126             :     }
     127             :     /* Now handle cmd_name -> cmd_num conversion */
     128           0 :     if (cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) {
     129           0 :         if ((e->cmd_defns == NULL)
     130           0 :             || ((idx = int_ctrl_cmd_by_name(e->cmd_defns, s)) < 0)) {
     131           0 :             ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NAME);
     132             :             return -1;
     133             :         }
     134           0 :         return e->cmd_defns[idx].cmd_num;
     135             :     }
     136             :     /*
     137             :      * For the rest of the commands, the 'long' argument must specify a valie
     138             :      * command number - so we need to conduct a search.
     139             :      */
     140           0 :     if ((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_num(e->cmd_defns,
     141             :                                                               (unsigned int)
     142             :                                                               i)) < 0)) {
     143           0 :         ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NUMBER);
     144             :         return -1;
     145             :     }
     146             :     /* Now the logic splits depending on command type */
     147           0 :     switch (cmd) {
     148             :     case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
     149           0 :         idx++;
     150           0 :         if (int_ctrl_cmd_is_null(e->cmd_defns + idx))
     151             :             /* end-of-list */
     152             :             return 0;
     153             :         else
     154           0 :             return e->cmd_defns[idx].cmd_num;
     155             :     case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
     156           0 :         return strlen(e->cmd_defns[idx].cmd_name);
     157             :     case ENGINE_CTRL_GET_NAME_FROM_CMD:
     158           0 :         return BIO_snprintf(s, strlen(e->cmd_defns[idx].cmd_name) + 1,
     159             :                             "%s", e->cmd_defns[idx].cmd_name);
     160             :     case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
     161           0 :         if (e->cmd_defns[idx].cmd_desc)
     162           0 :             return strlen(e->cmd_defns[idx].cmd_desc);
     163           0 :         return strlen(int_no_description);
     164             :     case ENGINE_CTRL_GET_DESC_FROM_CMD:
     165           0 :         if (e->cmd_defns[idx].cmd_desc)
     166           0 :             return BIO_snprintf(s,
     167           0 :                                 strlen(e->cmd_defns[idx].cmd_desc) + 1,
     168             :                                 "%s", e->cmd_defns[idx].cmd_desc);
     169           0 :         return BIO_snprintf(s, strlen(int_no_description) + 1, "%s",
     170             :                             int_no_description);
     171             :     case ENGINE_CTRL_GET_CMD_FLAGS:
     172           0 :         return e->cmd_defns[idx].cmd_flags;
     173             :     }
     174             :     /* Shouldn't really be here ... */
     175           0 :     ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INTERNAL_LIST_ERROR);
     176             :     return -1;
     177             : }
     178             : 
     179           0 : int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
     180             : {
     181             :     int ctrl_exists, ref_exists;
     182           0 :     if (e == NULL) {
     183           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL, ERR_R_PASSED_NULL_PARAMETER);
     184           0 :         return 0;
     185             :     }
     186           0 :     CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
     187           0 :     ref_exists = ((e->struct_ref > 0) ? 1 : 0);
     188           0 :     CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
     189           0 :     ctrl_exists = ((e->ctrl == NULL) ? 0 : 1);
     190           0 :     if (!ref_exists) {
     191           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_REFERENCE);
     192           0 :         return 0;
     193             :     }
     194             :     /*
     195             :      * Intercept any "root-level" commands before trying to hand them on to
     196             :      * ctrl() handlers.
     197             :      */
     198           0 :     switch (cmd) {
     199             :     case ENGINE_CTRL_HAS_CTRL_FUNCTION:
     200             :         return ctrl_exists;
     201             :     case ENGINE_CTRL_GET_FIRST_CMD_TYPE:
     202             :     case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
     203             :     case ENGINE_CTRL_GET_CMD_FROM_NAME:
     204             :     case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
     205             :     case ENGINE_CTRL_GET_NAME_FROM_CMD:
     206             :     case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
     207             :     case ENGINE_CTRL_GET_DESC_FROM_CMD:
     208             :     case ENGINE_CTRL_GET_CMD_FLAGS:
     209           0 :         if (ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL))
     210           0 :             return int_ctrl_helper(e, cmd, i, p, f);
     211           0 :         if (!ctrl_exists) {
     212           0 :             ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION);
     213             :             /*
     214             :              * For these cmd-related functions, failure is indicated by a -1
     215             :              * return value (because 0 is used as a valid return in some
     216             :              * places).
     217             :              */
     218           0 :             return -1;
     219             :         }
     220             :     default:
     221             :         break;
     222             :     }
     223             :     /* Anything else requires a ctrl() handler to exist. */
     224           0 :     if (!ctrl_exists) {
     225           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION);
     226           0 :         return 0;
     227             :     }
     228           0 :     return e->ctrl(e, cmd, i, p, f);
     229             : }
     230             : 
     231           0 : int ENGINE_cmd_is_executable(ENGINE *e, int cmd)
     232             : {
     233             :     int flags;
     234           0 :     if ((flags =
     235           0 :          ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0) {
     236           0 :         ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE,
     237             :                   ENGINE_R_INVALID_CMD_NUMBER);
     238           0 :         return 0;
     239             :     }
     240           0 :     if (!(flags & ENGINE_CMD_FLAG_NO_INPUT) &&
     241           0 :         !(flags & ENGINE_CMD_FLAG_NUMERIC) &&
     242             :         !(flags & ENGINE_CMD_FLAG_STRING))
     243             :         return 0;
     244           0 :     return 1;
     245             : }
     246             : 
     247           0 : int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
     248             :                     long i, void *p, void (*f) (void), int cmd_optional)
     249             : {
     250             :     int num;
     251             : 
     252           0 :     if ((e == NULL) || (cmd_name == NULL)) {
     253           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ERR_R_PASSED_NULL_PARAMETER);
     254           0 :         return 0;
     255             :     }
     256           0 :     if ((e->ctrl == NULL) || ((num = ENGINE_ctrl(e,
     257             :                                                  ENGINE_CTRL_GET_CMD_FROM_NAME,
     258             :                                                  0, (void *)cmd_name,
     259             :                                                  NULL)) <= 0)) {
     260             :         /*
     261             :          * If the command didn't *have* to be supported, we fake success.
     262             :          * This allows certain settings to be specified for multiple ENGINEs
     263             :          * and only require a change of ENGINE id (without having to
     264             :          * selectively apply settings). Eg. changing from a hardware device
     265             :          * back to the regular software ENGINE without editing the config
     266             :          * file, etc.
     267             :          */
     268           0 :         if (cmd_optional) {
     269           0 :             ERR_clear_error();
     270           0 :             return 1;
     271             :         }
     272           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ENGINE_R_INVALID_CMD_NAME);
     273           0 :         return 0;
     274             :     }
     275             :     /*
     276             :      * Force the result of the control command to 0 or 1, for the reasons
     277             :      * mentioned before.
     278             :      */
     279           0 :     if (ENGINE_ctrl(e, num, i, p, f) > 0)
     280             :         return 1;
     281           0 :     return 0;
     282             : }
     283             : 
     284           0 : int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
     285             :                            int cmd_optional)
     286             : {
     287             :     int num, flags;
     288             :     long l;
     289             :     char *ptr;
     290           0 :     if ((e == NULL) || (cmd_name == NULL)) {
     291           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
     292             :                   ERR_R_PASSED_NULL_PARAMETER);
     293           0 :         return 0;
     294             :     }
     295           0 :     if ((e->ctrl == NULL) || ((num = ENGINE_ctrl(e,
     296             :                                                  ENGINE_CTRL_GET_CMD_FROM_NAME,
     297             :                                                  0, (void *)cmd_name,
     298             :                                                  NULL)) <= 0)) {
     299             :         /*
     300             :          * If the command didn't *have* to be supported, we fake success.
     301             :          * This allows certain settings to be specified for multiple ENGINEs
     302             :          * and only require a change of ENGINE id (without having to
     303             :          * selectively apply settings). Eg. changing from a hardware device
     304             :          * back to the regular software ENGINE without editing the config
     305             :          * file, etc.
     306             :          */
     307           0 :         if (cmd_optional) {
     308           0 :             ERR_clear_error();
     309           0 :             return 1;
     310             :         }
     311           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ENGINE_R_INVALID_CMD_NAME);
     312           0 :         return 0;
     313             :     }
     314           0 :     if (!ENGINE_cmd_is_executable(e, num)) {
     315           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
     316             :                   ENGINE_R_CMD_NOT_EXECUTABLE);
     317           0 :         return 0;
     318             :     }
     319           0 :     if ((flags =
     320           0 :          ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL)) < 0) {
     321             :         /*
     322             :          * Shouldn't happen, given that ENGINE_cmd_is_executable() returned
     323             :          * success.
     324             :          */
     325           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
     326             :                   ENGINE_R_INTERNAL_LIST_ERROR);
     327           0 :         return 0;
     328             :     }
     329             :     /*
     330             :      * If the command takes no input, there must be no input. And vice versa.
     331             :      */
     332           0 :     if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
     333           0 :         if (arg != NULL) {
     334           0 :             ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
     335             :                       ENGINE_R_COMMAND_TAKES_NO_INPUT);
     336           0 :             return 0;
     337             :         }
     338             :         /*
     339             :          * We deliberately force the result of ENGINE_ctrl() to 0 or 1 rather
     340             :          * than returning it as "return data". This is to ensure usage of
     341             :          * these commands is consistent across applications and that certain
     342             :          * applications don't understand it one way, and others another.
     343             :          */
     344           0 :         if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0)
     345             :             return 1;
     346           0 :         return 0;
     347             :     }
     348             :     /* So, we require input */
     349           0 :     if (arg == NULL) {
     350           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
     351             :                   ENGINE_R_COMMAND_TAKES_INPUT);
     352           0 :         return 0;
     353             :     }
     354             :     /* If it takes string input, that's easy */
     355           0 :     if (flags & ENGINE_CMD_FLAG_STRING) {
     356             :         /* Same explanation as above */
     357           0 :         if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0)
     358             :             return 1;
     359           0 :         return 0;
     360             :     }
     361             :     /*
     362             :      * If it doesn't take numeric either, then it is unsupported for use in a
     363             :      * config-setting situation, which is what this function is for. This
     364             :      * should never happen though, because ENGINE_cmd_is_executable() was
     365             :      * used.
     366             :      */
     367           0 :     if (!(flags & ENGINE_CMD_FLAG_NUMERIC)) {
     368           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
     369             :                   ENGINE_R_INTERNAL_LIST_ERROR);
     370           0 :         return 0;
     371             :     }
     372           0 :     l = strtol(arg, &ptr, 10);
     373           0 :     if ((arg == ptr) || (*ptr != '\0')) {
     374           0 :         ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
     375             :                   ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER);
     376           0 :         return 0;
     377             :     }
     378             :     /*
     379             :      * Force the result of the control command to 0 or 1, for the reasons
     380             :      * mentioned before.
     381             :      */
     382           0 :     if (ENGINE_ctrl(e, num, l, NULL, NULL) > 0)
     383             :         return 1;
     384           0 :     return 0;
     385             : }

Generated by: LCOV version 1.10