oid.c
Go to the documentation of this file.
1 /**
2  * @file oid.c
3  * @brief OID (Object Identifier)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/crypto.h"
34 #include "encoding/oid.h"
35 #include "debug.h"
36 
37 //Check crypto library configuration
38 #if (OID_SUPPORT == ENABLED)
39 
40 
41 /**
42  * @brief Check whether the specified object identifier is valid
43  * @param[in] oid Pointer to the object identifier
44  * @param[in] oidLen Length of the OID, in bytes
45  * @return Error code
46  **/
47 
48 error_t oidCheck(const uint8_t *oid, size_t oidLen)
49 {
50  size_t i;
51  size_t n;
52 
53  //Check parameters
54  if(oid == NULL)
56 
57  //Check the length of the OID
58  if(oidLen == 0)
59  {
60  //Report an error
61  return ERROR_INVALID_SYNTAX;
62  }
63  else if(oidLen > 1)
64  {
65  //Parse the object identifier
66  for(i = 1, n = 2; i < oidLen; i++)
67  {
68  //Update the total number of nodes
69  if(!(oid[i] & OID_MORE_FLAG))
70  n++;
71 
72  //SNMP limits object identifier values to a maximum of 128 nodes
73  if(n > 128)
74  return ERROR_INVALID_SYNTAX;
75  }
76 
77  //Ensure that the last sub-identifier is valid
78  if(oid[oidLen - 1] & OID_MORE_FLAG)
79  return ERROR_INVALID_SYNTAX;
80  }
81 
82  //The specified OID is valid
83  return NO_ERROR;
84 }
85 
86 
87 /**
88  * @brief Compare object identifiers
89  * @param[in] oid1 Pointer the first OID
90  * @param[in] oidLen1 Length of the first OID, in bytes
91  * @param[in] oid2 Pointer the second OID
92  * @param[in] oidLen2 Length of the second OID, in bytes
93  * @return Comparison result
94  * @retval 0 Objects identifiers are equal
95  * @retval -1 The first OID lexicographically precedes the second OID
96  * @retval 1 The second OID lexicographically precedes the first OID
97  **/
98 
99 int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2,
100  size_t oidLen2)
101 {
102  size_t i;
103 
104  //Perform lexicographical comparison
105  for(i = 0; i < oidLen1 && i < oidLen2; i++)
106  {
107  //Compare current byte
108  if(oid1[i] < oid2[i])
109  return -1;
110  else if(oid1[i] > oid2[i])
111  return 1;
112  }
113 
114  //Compare length
115  if(oidLen1 < oidLen2)
116  return -1;
117  else if(oidLen1 > oidLen2)
118  return 1;
119 
120  //Object identifiers are equal
121  return 0;
122 }
123 
124 
125 /**
126  * @brief Check whether an OID matches the specified subtree
127  * @param[in] oid Pointer to the object identifier
128  * @param[in] oidLen Length of the OID, in bytes
129  * @param[in] subtree Pointer to the subtree
130  * @param[in] subtreeLen Length of the subtree, in bytes
131  * @param[in] mask Pointer to the mask
132  * @param[in] maskLen Length of the mask, in bytes
133  * @return TRUE if the OID matches the specified subtree, else FALSE
134  **/
135 
136 bool_t oidMatch(const uint8_t *oid, size_t oidLen, const uint8_t *subtree,
137  size_t subtreeLen, const uint8_t *mask, size_t maskLen)
138 {
139  size_t i;
140  uint8_t flag;
141  size_t oidPos;
142  size_t subtreePos;
143 
144  //Initialize variables
145  oidPos = 0;
146  subtreePos = 0;
147 
148  //Check whether the OID matches the specified subtree
149  for(i = 0; subtreePos < subtreeLen; i++)
150  {
151  //Check the length of the OID
152  if(oidPos >= oidLen)
153  return FALSE;
154 
155  //The bit mask is extended with 1's to be the required length
156  if((i / 8) < maskLen)
157  flag = mask[i / 8] & (1 << (7 - (i % 8)));
158  else
159  flag = 1;
160 
161  //First node?
162  if(i == 0)
163  {
164  //The mask allows for a simple form of wildcarding
165  if(flag)
166  {
167  //Compare the first sub-identifier
168  if((oid[0] / 40) != (subtree[0] / 40))
169  return FALSE;
170  }
171  }
172  //Second node?
173  else if(i == 1)
174  {
175  //The mask allows for a simple form of wildcarding
176  if(flag)
177  {
178  //Compare the second sub-identifier
179  if((oid[0] % 40) != (subtree[0] % 40))
180  return FALSE;
181  }
182 
183  //Jump to the next node
184  oidPos = 1;
185  subtreePos = 1;
186  }
187  //Remaining nodes?
188  else
189  {
190  //The mask allows for a simple form of wildcarding
191  if(flag)
192  {
193  //Compare sub-identifiers
194  while(1)
195  {
196  //Compare the current byte
197  if(oid[oidPos] != subtree[subtreePos])
198  return FALSE;
199 
200  //Bit b8 is set to zero to indicate the last byte
201  flag = oid[oidPos] & OID_MORE_FLAG;
202 
203  //Next byte
204  oidPos++;
205  subtreePos++;
206 
207  //Last byte of the sub-identifier?
208  if(!flag)
209  break;
210 
211  //Check the length of the OID
212  if(oidPos >= oidLen)
213  return FALSE;
214 
215  //Check the length of the subtree
216  if(subtreePos > subtreeLen)
217  return FALSE;
218  }
219  }
220  else
221  {
222  //Read the OID until the last byte of the sub-identifier is found
223  while(1)
224  {
225  //Bit b8 is set to zero to indicate the last byte
226  flag = oid[oidPos] & OID_MORE_FLAG;
227 
228  //Next byte
229  oidPos++;
230 
231  //Last byte of the sub-identifier?
232  if(!flag)
233  break;
234 
235  //Check the length of the OID
236  if(oidPos >= oidLen)
237  return FALSE;
238  }
239 
240  //Read the subtree until the last byte of the sub-identifier is found
241  while(1)
242  {
243  //Bit b8 is set to zero to indicate the last byte
244  flag = subtree[subtreePos] & OID_MORE_FLAG;
245 
246  //Next byte
247  subtreePos++;
248 
249  //Last byte of the sub-identifier?
250  if(!flag)
251  break;
252 
253  //Check the length of the subtree
254  if(subtreePos >= subtreeLen)
255  return FALSE;
256  }
257  }
258  }
259  }
260 
261  //The OID matches the specified subtree
262  return TRUE;
263 }
264 
265 
266 /**
267  * @brief Calculate the number of sub-identifiers
268  * @param[in] oid Pointer to the object identifier
269  * @param[in] oidLen Length of the OID, in bytes
270  * @return Number of sub-identifiers
271  **/
272 
273 uint_t oidCountSubIdentifiers(const uint8_t *oid, size_t oidLen)
274 {
275  size_t i;
276  uint_t n;
277 
278  //Check the length of the OID
279  if(oidLen == 0)
280  {
281  //The OID is empty
282  n = 0;
283  }
284  else
285  {
286  //The first byte encodes two sub-identifiers
287  n = 2;
288 
289  //Parse the object identifier
290  for(i = 1; i < oidLen; i++)
291  {
292  //Update the total number of sub-identifiers
293  if(!(oid[i] & OID_MORE_FLAG))
294  n++;
295  }
296  }
297 
298  //Return the total number of sub-identifiers
299  return n;
300 }
301 
302 
303 /**
304  * @brief Encode OID sub-identifier
305  * @param[in] oid Pointer to the object identifier
306  * @param[in] maxOidLen Maximum number of bytes the OID can hold
307  * @param[in,out] pos Offset where to write the sub-identifier
308  * @param[in] value Value of the sub-identifier
309  * @return Error code
310  **/
311 
312 error_t oidEncodeSubIdentifier(uint8_t *oid, size_t maxOidLen,
313  size_t *pos, uint32_t value)
314 {
315  size_t i;
316  size_t n;
317  uint8_t temp[5];
318 
319  //Encode the first byte of the sub-identifier
320  temp[0] = value & OID_VALUE_MASK;
321  //Shift the value to the right
322  value >>= 7;
323 
324  //Encode the remaining bytes
325  for(n = 1; value != 0; n++)
326  {
327  //Encode current byte
328  temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK);
329  //Shift the value to the right
330  value >>= 7;
331  }
332 
333  //Sanity check
334  if((*pos + n) > maxOidLen)
335  return ERROR_BUFFER_OVERFLOW;
336 
337  //Write the current sub-identifier
338  for(i = 0; i < n; i++)
339  oid[*pos + i] = temp[n - i - 1];
340 
341  //Update offset value
342  *pos += n;
343 
344  //Successful processing
345  return NO_ERROR;
346 }
347 
348 
349 /**
350  * @brief Decode OID sub-identifier
351  * @param[in] oid Pointer to the object identifier
352  * @param[in] oidLen Length of the OID, in bytes
353  * @param[in,out] pos Offset where to read the sub-identifier
354  * @param[out] value Value of the sub-identifier
355  * @return Error code
356  **/
357 
358 error_t oidDecodeSubIdentifier(const uint8_t *oid, size_t oidLen,
359  size_t *pos, uint32_t *value)
360 {
361  size_t i;
362 
363  //Initialize the value of the sub-identifier
364  *value = 0;
365 
366  //Read the OID until the last byte of the sub-identifier is found
367  for(i = *pos; i < oidLen; i++)
368  {
369  //Shift the value to the left
370  *value <<= 7;
371  //Update value of the sub-identifier
372  *value |= oid[i] & OID_VALUE_MASK;
373 
374  //Bit b8 is set to zero to indicate the last byte
375  if(!(oid[i] & OID_MORE_FLAG))
376  {
377  //Update offset value
378  *pos = i + 1;
379  //Successful processing
380  return NO_ERROR;
381  }
382  }
383 
384  //The specified OID is not valid
385  return ERROR_INVALID_SYNTAX;
386 }
387 
388 
389 /**
390  * @brief Convert a string representation of an OID to a binary OID
391  * @param[in] str NULL-terminated string representing the OID
392  * @param[out] oid Object identifier
393  * @param[in] maxOidLen Maximum number of bytes the OID can hold
394  * @param[out] oidLen Length of the object identifier
395  * @return Error code
396  **/
397 
398 error_t oidFromString(const char_t *str, uint8_t *oid, size_t maxOidLen,
399  size_t *oidLen)
400 {
401  error_t error;
402  size_t i;
403  size_t j;
404  size_t n;
405  uint32_t value;
406  uint8_t temp[5];
407 
408  //Reset the length of the OID
409  *oidLen = 0;
410 
411  //Number of nodes
412  i = 0;
413  //Initialize the value of the sub-identifier
414  value = 0;
415 
416  //Parse input string
417  while(1)
418  {
419  //Digit found?
420  if(cryptoIsdigit(*str))
421  {
422  //Update the value of the sub-identifier
423  value = (value * 10) + (*str - '0');
424  }
425  //Separator or end of string found?
426  else if(*str == '.' || *str == '\0')
427  {
428  //First node?
429  if(i == 0)
430  {
431  //Check value
432  if(value > 6)
433  {
434  //The conversion failed
435  error = ERROR_INVALID_SYNTAX;
436  break;
437  }
438 
439  //Encode the first sub-identifier
440  temp[0] = value * 40;
441  //Prepare to decode the next node
442  value = 0;
443  //Do not write current sub-identifier yet
444  n = 0;
445  }
446  //Second node?
447  else if(i == 1)
448  {
449  //Check value
450  if(value > 39)
451  {
452  //The conversion failed
453  error = ERROR_INVALID_SYNTAX;
454  break;
455  }
456 
457  //Encode the second sub-identifier
458  temp[0] += value;
459  //Prepare to decode the next node
460  value = 0;
461  //Write the first two sub-identifiers
462  n = 1;
463  }
464  //Remaining nodes?
465  else
466  {
467  //Encode the first byte of the sub-identifier
468  temp[0] = value & OID_VALUE_MASK;
469  //Shift the value to the right
470  value >>= 7;
471 
472  //Encode the remaining bytes
473  for(n = 1; value != 0; n++)
474  {
475  //Encode current byte
476  temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK);
477  //Shift the value to the right
478  value >>= 7;
479  }
480  }
481 
482  //Sanity check
483  if(n > maxOidLen)
484  {
485  //Report an error
486  error = ERROR_BUFFER_OVERFLOW;
487  break;
488  }
489 
490  //Write the current sub-identifier
491  for(j = 0; j < n; j++)
492  oid[j] = temp[n - j - 1];
493 
494  //Advance write pointer
495  oid += n;
496  *oidLen += n;
497  maxOidLen -= n;
498 
499  //Number of sub-identifiers
500  i++;
501 
502  //End of string detected?
503  if(*str == '\0')
504  {
505  //The conversion succeeded
506  error = NO_ERROR;
507  break;
508  }
509  }
510  //Invalid character...
511  else
512  {
513  //The conversion failed
514  error = ERROR_INVALID_SYNTAX;
515  break;
516  }
517 
518  //Point to the next character
519  str++;
520  }
521 
522  //Return status code
523  return error;
524 }
525 
526 
527 /**
528  * @brief Convert a binary OID to a string representation
529  * @param[in] oid Object identifier
530  * @param[in] oidLen Length of the object identifier, in bytes
531  * @param[out] str NULL-terminated string representing the OID
532  * @param[in] maxStrLen Maximum length of the resulting string
533  * @return Pointer to the formatted string
534  **/
535 
536 char_t *oidToString(const uint8_t *oid, size_t oidLen, char_t *str,
537  size_t maxStrLen)
538 {
539  static char_t buffer[128];
540  size_t i;
541  size_t n;
542  uint32_t value;
543  char_t *p;
544  char_t temp[12];
545 
546  //The str parameter is optional
547  if(str == NULL)
548  {
549  //Point to the internal buffer
550  str = buffer;
551  //Maximum length of the resulting string
552  maxStrLen = sizeof(buffer) - 1;
553  }
554 
555  //Point to the beginning of the string
556  p = str;
557  //Properly terminate the string
558  *p = '\0';
559 
560  //Check the length of the OID
561  if(oidLen > 0)
562  {
563  //Convert the first 2 bytes
564  n = sprintf(temp, "%" PRIu8 ".%" PRIu8 "", oid[0] / 40, oid[0] % 40);
565 
566  //Sanity check
567  if(n <= maxStrLen)
568  {
569  //Copy the resulting string
570  cryptoStrcpy(p, temp);
571  //Advance write pointer
572  p += n;
573  maxStrLen -= n;
574  }
575 
576  //Initialize the value of the sub-identifier
577  value = 0;
578 
579  //Convert the rest of the OID
580  for(i = 1; i < oidLen; i++)
581  {
582  //Shift the value to the left
583  value <<= 7;
584  //Update the current value
585  value |= oid[i] & OID_VALUE_MASK;
586 
587  //Bit b8 is set to zero to indicate the last byte
588  if(!(oid[i] & OID_MORE_FLAG))
589  {
590  //Dump current value
591  n = sprintf(temp, ".%" PRIu32, value);
592 
593  //Sanity check
594  if(n <= maxStrLen)
595  {
596  //Copy the resulting string
597  cryptoStrcpy(p, temp);
598  //Advance write pointer
599  p += n;
600  maxStrLen -= n;
601  }
602 
603  //Prepare to decode the next value
604  value = 0;
605  }
606  }
607  }
608 
609  //Return a pointer to the formatted string
610  return str;
611 }
612 
613 
614 /**
615  * @brief Convert a bit mask to binary representation
616  * @param[in] str NULL-terminated string representing the bit mask
617  * @param[out] mask Pointer to the buffer where to store the resulting mask
618  * @param[in] maxMaskLen Maximum number of bytes the buffer can hold
619  * @param[out] maskLen Length of the mask
620  * @return Error code
621  **/
622 
623 error_t maskFromString(const char_t *str, uint8_t *mask, size_t maxMaskLen,
624  size_t *maskLen)
625 {
626  error_t error;
627  size_t i;
628  size_t j;
629 
630  //Point to the first byte
631  i = 0;
632  //Point to the most-significant bit
633  j = 8;
634 
635  //Parse input string
636  while(1)
637  {
638  //Check current character
639  if(*str == '0' || *str == '1')
640  {
641  //Make sure the output buffer is large enough
642  if(i >= maxMaskLen)
643  {
644  //Report an error
645  error = ERROR_BUFFER_OVERFLOW;
646  break;
647  }
648 
649  //Update bit mask
650  if(*str == '1')
651  mask[i] |= (1 << (j - 1));
652  else
653  mask[i] &= ~(1 << (j - 1));
654 
655  //Next bit
656  j--;
657  }
658  else if(*str == '\0')
659  {
660  //End of string detected
661  error = NO_ERROR;
662  break;
663  }
664  else
665  {
666  //Discard any other characters
667  }
668 
669  //Check whether the least-significant bit has been reached
670  if(j == 0)
671  {
672  //Point to the most-significant bit of the next byte
673  j = 8;
674  i++;
675  }
676 
677  //Point to the next character
678  str++;
679  }
680 
681  //Check status code
682  if(!error)
683  {
684  //Incomplete byte?
685  if(j < 8)
686  {
687  //The bit mask is extended with 1's to be the required length
688  mask[i] |= (1 << j) - 1;
689  //Save the length of the resulting mask
690  *maskLen = i + 1;
691  }
692  else
693  {
694  //Save the length of the resulting mask
695  *maskLen = i;
696  }
697  }
698 
699  //Return status code
700  return error;
701 }
702 
703 #endif
char char_t
Definition: compiler_port.h:41
char_t * oidToString(const uint8_t *oid, size_t oidLen, char_t *str, size_t maxStrLen)
Convert a binary OID to a string representation.
Definition: oid.c:536
Debugging facilities.
uint8_t p
Definition: ndp.h:295
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:45
#define cryptoIsdigit(c)
Definition: crypto.h:632
OID (Object Identifier)
#define TRUE
Definition: os_port.h:48
uint8_t mask
Definition: web_socket.h:315
error_t oidEncodeSubIdentifier(uint8_t *oid, size_t maxOidLen, size_t *pos, uint32_t value)
Encode OID sub-identifier.
Definition: oid.c:312
error_t oidFromString(const char_t *str, uint8_t *oid, size_t maxOidLen, size_t *oidLen)
Convert a string representation of an OID to a binary OID.
Definition: oid.c:398
signed int int_t
Definition: compiler_port.h:42
#define cryptoStrcpy(s1, s2)
Definition: crypto.h:614
uint_t oidCountSubIdentifiers(const uint8_t *oid, size_t oidLen)
Calculate the number of sub-identifiers.
Definition: oid.c:273
#define OID_MORE_FLAG
Definition: oid.h:36
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:99
error_t oidDecodeSubIdentifier(const uint8_t *oid, size_t oidLen, size_t *pos, uint32_t *value)
Decode OID sub-identifier.
Definition: oid.c:358
bool_t oidMatch(const uint8_t *oid, size_t oidLen, const uint8_t *subtree, size_t subtreeLen, const uint8_t *mask, size_t maskLen)
Check whether an OID matches the specified subtree.
Definition: oid.c:136
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
#define OID_VALUE_MASK
Definition: oid.h:37
unsigned int uint_t
Definition: compiler_port.h:43
error_t maskFromString(const char_t *str, uint8_t *mask, size_t maxMaskLen, size_t *maskLen)
Convert a bit mask to binary representation.
Definition: oid.c:623
uint8_t value[]
Definition: dtls_misc.h:141
error_t oidCheck(const uint8_t *oid, size_t oidLen)
Check whether the specified object identifier is valid.
Definition: oid.c:48
uint8_t n
uint8_t oid[1]
Definition: mib_common.h:184
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47