Webserver+3d print

Dependents:   Nucleo

cyclone_crypto/oid.c

Committer:
Sergunb
Date:
2017-02-04
Revision:
0:8918a71cdbe9

File content as of revision 0:8918a71cdbe9:

/**
 * @file oid.c
 * @brief OID (Object Identifier)
 *
 * @section License
 *
 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneCrypto Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 1.7.6
 **/

//Switch to the appropriate trace level
#define TRACE_LEVEL CRYPTO_TRACE_LEVEL

//Dependencies
#include <string.h>
#include <ctype.h>
#include "crypto.h"
#include "oid.h"
#include "debug.h"

//Check crypto library configuration
#if (OID_SUPPORT == ENABLED)


/**
* @brief Check whether the specified object identifier is valid
* @param[in] oid Pointer to the object identifier
* @param[in] oidLen Length of the OID, in bytes
* @return Error code
**/

error_t oidCheck(const uint8_t *oid, size_t oidLen)
{
   size_t i;
   size_t n;

   //Check parameters
   if(oid == NULL)
      return ERROR_INVALID_PARAMETER;

   //Check the length of the OID
   if(oidLen == 0)
   {
      //Report an error
      return ERROR_INVALID_SYNTAX;
   }
   else if(oidLen > 1)
   {
      //Parse the object identifier
      for(i = 1, n = 2; i < oidLen; i++)
      {
         //Update the total number of nodes
         if(!(oid[i] & OID_MORE_FLAG))
            n++;

         //SNMP limits object identifier values to a maximum of 128 nodes
         if(n > 128)
            return ERROR_INVALID_SYNTAX;
      }

      //Ensure that the last sub-identifier is valid
      if(oid[oidLen - 1] & OID_MORE_FLAG)
         return ERROR_INVALID_SYNTAX;
   }

   //The specified OID is valid
   return NO_ERROR;
}


/**
 * @brief Compare object identifiers
 * @param[in] oid1 Pointer the first OID
 * @param[in] oidLen1 Length of the first OID, in bytes
 * @param[in] oid2 Pointer the second OID
 * @param[in] oidLen2 Length of the second OID, in bytes
 * @return Comparison result
 * @retval 0 Objects identifiers are equal
 * @retval -1 The first OID lexicographically precedes the second OID
 * @retval 1 The second OID lexicographically precedes the first OID
 **/

int_t oidComp(const uint8_t *oid1, size_t oidLen1,
   const uint8_t *oid2, size_t oidLen2)
{
   size_t i;

   //Perform lexicographical comparison
   for(i = 0; i < oidLen1 && i < oidLen2; i++)
   {
      //Compare current byte
      if(oid1[i] < oid2[i])
         return -1;
      else if(oid1[i] > oid2[i])
         return 1;
   }

   //Compare length
   if(oidLen1 < oidLen2)
      return -1;
   else if(oidLen1 > oidLen2)
      return 1;

   //Object identifiers are equal
   return 0;
}


/**
 * @brief Encode OID sub-identifier
 * @param[in] oid Pointer to the object identifier
 * @param[in] maxOidLen Maximum number of bytes the OID can hold
 * @param[in,out] pos Offset where to write the sub-identifier
 * @param[in] value Value of the sub-identifier
 * @return Error code
 **/

error_t oidEncodeSubIdentifier(uint8_t *oid,
   size_t maxOidLen, size_t *pos, uint32_t value)
{
   size_t i;
   size_t n;
   uint8_t temp[5];

   //Encode the first byte of the sub-identifier
   temp[0] = value & OID_VALUE_MASK;
   //Shift the value to the right
   value >>= 7;

   //Encode the remaining bytes
   for(n = 1; value != 0; n++)
   {
      //Encode current byte
      temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK);
      //Shift the value to the right
      value >>= 7;
   }

   //Sanity check
   if((*pos + n) > maxOidLen)
      return ERROR_BUFFER_OVERFLOW;

   //Write the current sub-identifier
   for(i = 0; i < n; i++)
      oid[*pos + i] = temp[n - i - 1];

   //Update offset value
   *pos += n;

   //Successful processing
   return NO_ERROR;
}


/**
 * @brief Decode OID sub-identifier
 * @param[in] oid Pointer to the object identifier
 * @param[in] oidLen Length of the OID, in bytes
 * @param[in,out] pos Offset where to read the sub-identifier
 * @param[out] value Value of the sub-identifier
 * @return Error code
 **/

error_t oidDecodeSubIdentifier(const uint8_t *oid,
   size_t oidLen, size_t *pos, uint32_t *value)
{
   size_t i;

   //Initialize the value of the sub-identifier
   *value = 0;

   //Read the OID until the last byte of the sub-identifier is found
   for(i = *pos; i < oidLen; i++)
   {
      //Shift the value to the left
      *value <<= 7;
      //Update value of the sub-identifier
      *value |= oid[i] & OID_VALUE_MASK;

      //Bit b8 is set to zero to indicate the last byte
      if(!(oid[i] & OID_MORE_FLAG))
      {
         //Update offset value
         *pos = i + 1;
         //Successful processing
         return NO_ERROR;
      }
   }

   //The specified OID is not valid
   return ERROR_INVALID_SYNTAX;
}


/**
 * @brief Convert a string representation of an OID to a binary OID
 * @param[in] str NULL-terminated string representing the OID
 * @param[out] oid Object identifier
 * @param[in] maxOidLen Maximum number of bytes the OID can hold
 * @param[out] oidLen Length of the object identifier
 * @return Error code
 **/

error_t oidFromString(const char_t *str,
   uint8_t *oid, size_t maxOidLen, size_t *oidLen)
{
   error_t error;
   size_t i;
   size_t j;
   size_t n;
   uint32_t value;
   uint8_t temp[5];

   //Reset the length of the OID
   *oidLen = 0;

   //Number of nodes
   i = 0;
   //Initialize the value of the sub-identifier
   value = 0;

   //Parse input string
   while(1)
   {
      //Digit found?
      if(isdigit((uint8_t) *str))
      {
         //Update the value of the sub-identifier
         value = (value * 10) + (*str - '0');
      }
      //Separator or end of string found?
      else if(*str == '.' || *str == '\0')
      {
         //First node?
         if(i == 0)
         {
            //Check value
            if(value > 6)
            {
               //The conversion failed
               error = ERROR_INVALID_SYNTAX;
               break;
            }

            //Encode the first sub-identifier
            temp[0] = value * 40;
            //Prepare to decode the next node
            value = 0;
            //Do not write current sub-identifier yet
            n = 0;
         }
         //Second node?
         else if(i == 1)
         {
            //Check value
            if(value > 39)
            {
               //The conversion failed
               error = ERROR_INVALID_SYNTAX;
               break;
            }

            //Encode the second sub-identifier
            temp[0] |= value;
            //Prepare to decode the next node
            value = 0;
            //Write the first two sub-identifiers
            n = 1;
         }
         //Remaining nodes?
         else
         {
            //Encode the first byte of the sub-identifier
            temp[0] = value & OID_VALUE_MASK;
            //Shift the value to the right
            value >>= 7;

            //Encode the remaining bytes
            for(n = 1; value != 0; n++)
            {
               //Encode current byte
               temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK);
               //Shift the value to the right
               value >>= 7;
            }
         }

         //Sanity check
         if(n > maxOidLen)
         {
            //Report an error
            error = ERROR_BUFFER_OVERFLOW;
            break;
         }

         //Write the current sub-identifier
         for(j = 0; j < n; j++)
            oid[j] = temp[n - j - 1];

         //Advance write pointer
         oid += n;
         *oidLen += n;
         maxOidLen -= n;

         //Number of sub-identifiers
         i++;

         //End of string detected?
         if(*str == '\0')
         {
            //The conversion succeeded
            error = NO_ERROR;
            break;
         }
      }
      //Invalid character...
      else
      {
         //The conversion failed
         error = ERROR_INVALID_SYNTAX;
         break;
      }

      //Point to the next character
      str++;
   }

   //Return status code
   return error;
}


/**
 * @brief Convert a binary OID to a string representation
 * @param[in] oid Object identifier
 * @param[in] oidLen Length of the object identifier, in bytes
 * @param[out] str NULL-terminated string representing the OID
 * @param[in] maxStrLen Maximum length of the resulting string
 * @return Pointer to the formatted string
 **/

char_t *oidToString(const uint8_t *oid,
   size_t oidLen, char_t *str, size_t maxStrLen)
{
   static char_t buffer[64];
   size_t i;
   size_t n;
   uint32_t value;
   char_t *p;
   char_t temp[12];

   //The str parameter is optional
   if(str == NULL)
   {
      //Point to the internal buffer
      str = buffer;
      //Maximum length of the resulting string
      maxStrLen = sizeof(buffer) - 1;
   }

   //Point the beginning of the string
   p = str;
   //Properly terminate the string
   *p = '\0';

   //Check the length of the OID
   if(oidLen > 0)
   {
      //Convert the first 2 bytes
      n = sprintf(temp, "%" PRIu8 ".%" PRIu8 "", oid[0] / 40, oid[0] % 40);

      //Sanity check
      if(n <= maxStrLen)
      {
         //Copy the resulting string
         strcpy(p, temp);
         //Advance write pointer
         p += n;
         maxStrLen -= n;
      }

      //Initialize the value of the sub-identifier
      value = 0;

      //Convert the rest of the OID
      for(i = 1; i < oidLen; i++)
      {
         //Shift the value to the left
         value <<= 7;
         //Update the current value
         value |= oid[i] & OID_VALUE_MASK;

         //Bit b8 is set to zero to indicate the last byte
         if(!(oid[i] & OID_MORE_FLAG))
         {
            //Dump current value
            n = sprintf(temp, ".%" PRIu32, value);

            //Sanity check
            if(n <= maxStrLen)
            {
               //Copy the resulting string
               strcpy(p, temp);
               //Advance write pointer
               p += n;
               maxStrLen -= n;
            }

            //Prepare to decode the next value
            value = 0;
         }
      }
   }

   //Return a pointer to the formatted string
   return str;
}

#endif