/trunk/LICENSE |
---|
0,0 → 1,202 |
Apache License |
Version 2.0, January 2004 |
http://www.apache.org/licenses/ |
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
1. Definitions. |
"License" shall mean the terms and conditions for use, reproduction, |
and distribution as defined by Sections 1 through 9 of this document. |
"Licensor" shall mean the copyright owner or entity authorized by |
the copyright owner that is granting the License. |
"Legal Entity" shall mean the union of the acting entity and all |
other entities that control, are controlled by, or are under common |
control with that entity. For the purposes of this definition, |
"control" means (i) the power, direct or indirect, to cause the |
direction or management of such entity, whether by contract or |
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
outstanding shares, or (iii) beneficial ownership of such entity. |
"You" (or "Your") shall mean an individual or Legal Entity |
exercising permissions granted by this License. |
"Source" form shall mean the preferred form for making modifications, |
including but not limited to software source code, documentation |
source, and configuration files. |
"Object" form shall mean any form resulting from mechanical |
transformation or translation of a Source form, including but |
not limited to compiled object code, generated documentation, |
and conversions to other media types. |
"Work" shall mean the work of authorship, whether in Source or |
Object form, made available under the License, as indicated by a |
copyright notice that is included in or attached to the work |
(an example is provided in the Appendix below). |
"Derivative Works" shall mean any work, whether in Source or Object |
form, that is based on (or derived from) the Work and for which the |
editorial revisions, annotations, elaborations, or other modifications |
represent, as a whole, an original work of authorship. For the purposes |
of this License, Derivative Works shall not include works that remain |
separable from, or merely link (or bind by name) to the interfaces of, |
the Work and Derivative Works thereof. |
"Contribution" shall mean any work of authorship, including |
the original version of the Work and any modifications or additions |
to that Work or Derivative Works thereof, that is intentionally |
submitted to Licensor for inclusion in the Work by the copyright owner |
or by an individual or Legal Entity authorized to submit on behalf of |
the copyright owner. For the purposes of this definition, "submitted" |
means any form of electronic, verbal, or written communication sent |
to the Licensor or its representatives, including but not limited to |
communication on electronic mailing lists, source code control systems, |
and issue tracking systems that are managed by, or on behalf of, the |
Licensor for the purpose of discussing and improving the Work, but |
excluding communication that is conspicuously marked or otherwise |
designated in writing by the copyright owner as "Not a Contribution." |
"Contributor" shall mean Licensor and any individual or Legal Entity |
on behalf of whom a Contribution has been received by Licensor and |
subsequently incorporated within the Work. |
2. Grant of Copyright License. Subject to the terms and conditions of |
this License, each Contributor hereby grants to You a perpetual, |
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
copyright license to reproduce, prepare Derivative Works of, |
publicly display, publicly perform, sublicense, and distribute the |
Work and such Derivative Works in Source or Object form. |
3. Grant of Patent License. Subject to the terms and conditions of |
this License, each Contributor hereby grants to You a perpetual, |
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
(except as stated in this section) patent license to make, have made, |
use, offer to sell, sell, import, and otherwise transfer the Work, |
where such license applies only to those patent claims licensable |
by such Contributor that are necessarily infringed by their |
Contribution(s) alone or by combination of their Contribution(s) |
with the Work to which such Contribution(s) was submitted. If You |
institute patent litigation against any entity (including a |
cross-claim or counterclaim in a lawsuit) alleging that the Work |
or a Contribution incorporated within the Work constitutes direct |
or contributory patent infringement, then any patent licenses |
granted to You under this License for that Work shall terminate |
as of the date such litigation is filed. |
4. Redistribution. You may reproduce and distribute copies of the |
Work or Derivative Works thereof in any medium, with or without |
modifications, and in Source or Object form, provided that You |
meet the following conditions: |
(a) You must give any other recipients of the Work or |
Derivative Works a copy of this License; and |
(b) You must cause any modified files to carry prominent notices |
stating that You changed the files; and |
(c) You must retain, in the Source form of any Derivative Works |
that You distribute, all copyright, patent, trademark, and |
attribution notices from the Source form of the Work, |
excluding those notices that do not pertain to any part of |
the Derivative Works; and |
(d) If the Work includes a "NOTICE" text file as part of its |
distribution, then any Derivative Works that You distribute must |
include a readable copy of the attribution notices contained |
within such NOTICE file, excluding those notices that do not |
pertain to any part of the Derivative Works, in at least one |
of the following places: within a NOTICE text file distributed |
as part of the Derivative Works; within the Source form or |
documentation, if provided along with the Derivative Works; or, |
within a display generated by the Derivative Works, if and |
wherever such third-party notices normally appear. The contents |
of the NOTICE file are for informational purposes only and |
do not modify the License. You may add Your own attribution |
notices within Derivative Works that You distribute, alongside |
or as an addendum to the NOTICE text from the Work, provided |
that such additional attribution notices cannot be construed |
as modifying the License. |
You may add Your own copyright statement to Your modifications and |
may provide additional or different license terms and conditions |
for use, reproduction, or distribution of Your modifications, or |
for any such Derivative Works as a whole, provided Your use, |
reproduction, and distribution of the Work otherwise complies with |
the conditions stated in this License. |
5. Submission of Contributions. Unless You explicitly state otherwise, |
any Contribution intentionally submitted for inclusion in the Work |
by You to the Licensor shall be under the terms and conditions of |
this License, without any additional terms or conditions. |
Notwithstanding the above, nothing herein shall supersede or modify |
the terms of any separate license agreement you may have executed |
with Licensor regarding such Contributions. |
6. Trademarks. This License does not grant permission to use the trade |
names, trademarks, service marks, or product names of the Licensor, |
except as required for reasonable and customary use in describing the |
origin of the Work and reproducing the content of the NOTICE file. |
7. Disclaimer of Warranty. Unless required by applicable law or |
agreed to in writing, Licensor provides the Work (and each |
Contributor provides its Contributions) on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
implied, including, without limitation, any warranties or conditions |
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
PARTICULAR PURPOSE. You are solely responsible for determining the |
appropriateness of using or redistributing the Work and assume any |
risks associated with Your exercise of permissions under this License. |
8. Limitation of Liability. In no event and under no legal theory, |
whether in tort (including negligence), contract, or otherwise, |
unless required by applicable law (such as deliberate and grossly |
negligent acts) or agreed to in writing, shall any Contributor be |
liable to You for damages, including any direct, indirect, special, |
incidental, or consequential damages of any character arising as a |
result of this License or out of the use or inability to use the |
Work (including but not limited to damages for loss of goodwill, |
work stoppage, computer failure or malfunction, or any and all |
other commercial damages or losses), even if such Contributor |
has been advised of the possibility of such damages. |
9. Accepting Warranty or Additional Liability. While redistributing |
the Work or Derivative Works thereof, You may choose to offer, |
and charge a fee for, acceptance of support, warranty, indemnity, |
or other liability obligations and/or rights consistent with this |
License. However, in accepting such obligations, You may act only |
on Your own behalf and on Your sole responsibility, not on behalf |
of any other Contributor, and only if You agree to indemnify, |
defend, and hold each Contributor harmless for any liability |
incurred by, or claims asserted against, such Contributor by reason |
of your accepting any such warranty or additional liability. |
END OF TERMS AND CONDITIONS |
APPENDIX: How to apply the Apache License to your work. |
To apply the Apache License to your work, attach the following |
boilerplate notice, with the fields enclosed by brackets "[]" |
replaced with your own identifying information. (Don't include |
the brackets!) The text should be enclosed in the appropriate |
comment syntax for the file format. We also recommend that a |
file or class name and description of purpose be included on the |
same "printed page" as the copyright notice for easier |
identification within third-party archives. |
Copyright 2018 Daniel Marschall, ViaThinkSoft |
Licensed under the Apache License, Version 2.0 (the "License"); |
you may not use this file except in compliance with the License. |
You may obtain a copy of the License at |
http://www.apache.org/licenses/LICENSE-2.0 |
Unless required by applicable law or agreed to in writing, software |
distributed under the License is distributed on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
See the License for the specific language governing permissions and |
limitations under the License. |
/trunk/README.md |
---|
0,0 → 1,29 |
# OID/DER converter for C and PHP |
Current version: [1.3](https://github.com/m9aertner/oidConverter)+viathinksoft12 |
## Functionalities |
- Encode **absolute** OID in dot-notation (`"2.999.1234"`) into Hex-String (`"06 04 88 37 89 52"`) |
- Encode **absolute** OID in dot-notation (`"2.999.1234"`) into C-Hex-String (`"\x06\x04\x88\x37\x89\x52"`) |
- Encode **absolute** OID in dot-notation (`"2.999.1234"`) into C-Array (`{ 0x06, 0x04, 0x88, 0x37, 0x89, 0x52 }`) |
- Encode **relative** OID in dot-notation (`"1234"`) into Hex-String (`"0D 02 89 52"`) |
- Encode **relative** OID in dot-notation (`"1234"`) into C-Hex-String (`"\x0D\x02\x89\x52"`) |
- Encode **relative** OID in dot-notation (`"1234"`) into C-Array (`{ 0x0D, 0x02, 0x89, 0x52 }`) |
- Decode Hex-Notation (`"06 04 88 37 89 52"` or `"\x06\x04\x88\x37\x89\x52"` or `{ 0x06, 0x04, 0x88, 0x37, 0x89, 0x52 }`) into dot-notation (`"2.999.1234"`) |
## Acknowledgements |
Object ID converter by [Matthias Gärtner](http://www.rtner.de/software/oid.html), 06/1999. Converted to plain 'C' 07/2001. |
Heavily improved version by Daniel Marschall, ViaThinkSoft June-July 2011. |
Translated from C to PHP by Daniel Marschall, ViaThinkSoft. |
September 2022: Synchronized to upstream version 1.3 (added `-c` argument). |
## License |
Work of original author: "Freeware - do with it whatever you want. Use at your own risk. No warranty of any kind." |
Work of Daniel Marschall (PHP): Licensed under the Apache 2.0 license |
/trunk/c/Makefile |
---|
0,0 → 1,7 |
all: |
gcc -O2 -o oid oid.c -lm -lgmp |
clean: |
rm -f *.o |
# TODO: if [ -f ... ] then rm |
rm oid |
/trunk/c/oid |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/c/oid.c |
---|
0,0 → 1,948 |
/*################################################################################# |
### ### |
### Object ID converter. Matthias Gaertner, 06/1999 ### |
### Converted to plain 'C' 07/2001 ### |
### ### |
### Enhanced version by Daniel Marschall, ViaThinkSoft 06-07/2011, 2022 ### |
### based on (or rather synchronized to) upstream version 1.3 ### |
### -- NEW in +viathinksoft2: 2.48 can also be encoded! ### |
### -- NEW in +viathinksoft2: UUIDs (128-bit) are now supported! ### |
### (requires GMPLib) ### |
### -- NEW in +viathinksoft3: Length can now have more than 1 byte ### |
### -- NEW in +viathinksoft4: No command line limitation anymore. ### |
### -- NEW in +viathinksoft5: Now also relative OIDs supported ### |
### -- NEW in +viathinksoft6: 0x80 paddings are now disallowed ### |
### -- NEW in +viathinksoft8: Removed Application/Context/Private "OID"s ### |
### -- NEW in +viathinksoft9: Also allow decoding C-notation with "-x" ### |
### -- AS WELL AS SEVERAL BUG FIXES ### |
### ### |
### To compile with gcc simply use: ### |
### gcc -O2 -o oid oid.c -lgmp -lm ### |
### ### |
### To compile using lcc-win32, use: ### |
### lcc oid.c & lcclnk oid.obj ### |
### ### |
### To compile using cl, use: ### |
### cl -DWIN32 -O1 oid.c (+ include gmp library) ### |
### ### |
### Freeware - do with it whatever you want. ### |
### Use at your own risk. No warranty of any kind. ### |
### ### |
#################################################################################*/ |
/* $Version: 1.3+viathinksoft12$ */ |
// FUTURE |
// - Alles in Funktionen kapseln. Als Parameter: Array of integer (= dot notation) oder Array of byte (= hex notation) |
// MINOR THINGS |
// - All stderr: Output new line at stdOut and close stdOut |
// - Make as much GMP as possible (e.g. nBinary counter, nBinaryWork etc) |
// - Think aout how to better define the return codes (error codes) |
// - irgendwie in funktionen kapseln (z.b. class-tag-parser usw) |
// - Look at all "TODO"s (especially things which are not clear) |
// MINOR PROBLEMS IN CLI-INTERPRETATION: |
// - A wrong error message is shown when trying to encode "-0.0" or "x" |
// - 2.9a9 is not recognized as error |
// - "./oid R 2.999" is not interpretet correctly |
// - "./oid .2.999" will be interpreted as "0.2.999" |
// NICE TO HAVE: |
// - makefile, manpage, linuxpackage |
// - better make functions instead of putting everything in main() with fprintf... |
// NICE TO HAVE (INFINITY-IDEA - NOT IMPORTANT): |
// - Is it possible to detect integer overflows and therefore output errors? |
// ------------------------------------------------------- |
// Allows OIDs which are bigger than "long" |
// Compile with "gcc oid.c -lgmp -lm" |
#define is_gmp |
#include <stdio.h> |
#include <string.h> |
#include <stdlib.h> |
#ifdef is_gmp |
#include <gmp.h> |
#endif |
#include <stdbool.h> |
#ifndef __STRNICMP_LOCAL |
#ifdef WIN32 |
#define __STRNICMP_LOCAL strnicmp |
#else |
#define __STRNICMP_LOCAL strncasecmp |
#endif |
#endif |
// char abCommandLine[4096]; |
const unsigned int CLI_INITIAL_SIZE = 1024; |
const unsigned int CLI_EXPANSION_SIZE = 1024; |
unsigned int cli_size; |
char * abCommandLine; |
// unsigned char abBinary[128]; |
const unsigned int ABB_INITIAL_SIZE = 1024; |
const unsigned int ABB_EXPANSION_SIZE = 1024; |
unsigned int abb_size; |
unsigned char * abBinary; |
unsigned int nBinary = 0; |
const int MODE_DOT_TO_HEX = 0; |
const int MODE_HEX_TO_DOT = 1; |
#ifdef is_gmp |
static void MakeBase128(mpz_t l, int first) { |
if (mpz_cmp_si(l, 127) > 0) { |
mpz_t l2; |
mpz_init(l2); |
mpz_div_ui(l2, l, 128); |
MakeBase128(l2, 0); |
} |
mpz_mod_ui(l, l, 128); |
if (nBinary+1 >= abb_size) { |
abb_size += ABB_EXPANSION_SIZE; |
abBinary = (unsigned char*) realloc(abBinary, abb_size); |
if (abBinary == NULL) { |
fprintf(stderr, "Memory reallocation failure!\n"); |
exit(EXIT_FAILURE); |
} |
} |
if (first) { |
abBinary[nBinary++] = mpz_get_ui(l); |
} else { |
abBinary[nBinary++] = 0x80 | mpz_get_ui(l); |
} |
} |
#else |
static void MakeBase128(unsigned long l, int first) { |
if (l > 127) { |
MakeBase128(l / 128, 0); |
} |
l %= 128; |
if (nBinary+1 >= abb_size) { |
abb_size += ABB_EXPANSION_SIZE; |
abBinary = (unsigned char*) realloc(abBinary, abb_size); |
if (abBinary == NULL) { |
fprintf(stderr, "Memory reallocation failure!\n"); |
exit(EXIT_FAILURE); |
} |
} |
if (first) { |
abBinary[nBinary++] = (unsigned char)l; |
} else { |
abBinary[nBinary++] = 0x80 | (unsigned char)l; |
} |
} |
#endif |
int main(int argc, char **argv) { |
cli_size = CLI_INITIAL_SIZE; |
abCommandLine = (char*) malloc(cli_size * sizeof(char*)); |
if (abCommandLine == NULL) { |
fprintf(stderr, "Memory allocation failure!\n"); |
return EXIT_FAILURE; |
} |
abb_size = ABB_INITIAL_SIZE; |
abBinary = (unsigned char*) malloc(abb_size * sizeof(unsigned char*)); |
if (abBinary == NULL) { |
fprintf(stderr, "Memory allocation failure!\n"); |
return EXIT_FAILURE; |
} |
char *fOutName = NULL; |
char *fInName = NULL; |
FILE *fOut = NULL; |
int n = 1; |
int nMode = MODE_DOT_TO_HEX; |
int nCHex = 0; |
int nAfterOption = 0; |
bool isRelative = false; |
if (argc == 1) { |
fprintf(stderr, |
"OID encoder/decoder 1.3+viathinksoft12 - Matthias Gaertner 1999/2001, Daniel Marschall 2011/2012 - Freeware\n" |
#ifdef is_gmp |
"GMP Edition (unlimited arc sizes)\n" |
#else |
"%d-bit Edition (arc sizes are limited!)\n" |
#endif |
"\nUsage:\n" |
" OID [-c|-C] [-r] [-o<outfile>] {-i<infile>|2.999.1}\n" |
" converts dotted form to ASCII HEX DER output.\n" |
" -c: Output as C-syntax (array).\n" |
" -C: Output as C-syntax (string).\n" |
" -r: Handle the OID as relative and not absolute.\n" |
" OID -x [-o<outfile>] {-i<infile>|hex-digits}\n" |
" decodes ASCII HEX DER and gives dotted form.\n" , sizeof(unsigned long) * 8); |
return 1; |
} |
while (n < argc) { |
if (!nAfterOption && argv[n][0] == '-') { |
if (argv[n][1] == 'x') { |
nMode = MODE_HEX_TO_DOT; |
if (argv[n][2] != '\0') { |
argv[n--] += 2; |
nAfterOption = 1; |
} |
} else if (argv[n][1] == 'c') { |
nMode = MODE_DOT_TO_HEX; |
nCHex = 1; |
if (argv[n][2] != '\0') { |
argv[n--] += 2; |
nAfterOption = 1; |
} |
} else if (argv[n][1] == 'C') { |
nMode = MODE_DOT_TO_HEX; |
nCHex = 2; |
if (argv[n][2] != '\0') { |
argv[n--] += 2; |
nAfterOption = 1; |
} |
} else if (argv[n][1] == 'r') { |
nMode = MODE_DOT_TO_HEX; |
isRelative = true; |
if (argv[n][2] != '\0') { |
argv[n--] += 2; |
nAfterOption = 1; |
} |
} else if (argv[n][1] == 'o') { |
if (argv[n][2] != '\0') { |
fOutName = &argv[n][2]; |
} else if (n < argc-1) { |
fOutName = argv[++n]; |
} else { |
fprintf(stderr, "Incomplete command line.\n"); |
return EXIT_FAILURE; |
} |
} else if (argv[n][1] == 'i') { |
if (argv[n][2] != '\0') { |
fInName = &argv[n][2]; |
} else if (n < argc-1) { |
fInName = argv[++n]; |
} else { |
fprintf(stderr, "Incomplete command line.\n"); |
return EXIT_FAILURE; |
} |
} |
} else { |
if (fInName != NULL) { // TODO: (Not clear): What does this? Is this also important for fOutName? |
break; |
} |
nAfterOption = 1; |
if (strlen(argv[n]) + strlen(abCommandLine) >= sizeof(abCommandLine)-2) { // TODO: warum -2 ? |
// fprintf(stderr, "Command line too long.\n"); |
// return 2; |
cli_size += CLI_EXPANSION_SIZE + strlen(argv[n]) + 1; // 1 = "." |
abCommandLine = (char*) realloc(abCommandLine, cli_size); |
if (abCommandLine == NULL) { |
fprintf(stderr, "Memory reallocation failure!\n"); |
return EXIT_FAILURE; |
} |
} |
strcat(abCommandLine, argv[n]); // (automatically inserts an "\0") |
if (n != argc - 1 && nMode != MODE_HEX_TO_DOT) { |
strcat(abCommandLine, "."); |
} |
} |
n++; |
} |
if (fInName != NULL && nMode == MODE_HEX_TO_DOT) { |
FILE *fIn = fopen(fInName, "rb"); |
size_t nRead = 0; |
if (fIn == NULL) { |
fprintf(stderr, "Unable to open input file %s.\n", fInName); |
return 11; |
} |
nRead = fread(abCommandLine, 1, sizeof(abCommandLine), fIn); |
abCommandLine[nRead] = '\0'; |
fclose(fIn); |
} else if (fInName != NULL && nMode == MODE_DOT_TO_HEX) { |
FILE *fIn = fopen(fInName, "rt"); |
if (fIn == NULL) { |
fprintf(stderr, "Unable to open input file %s.\n", fInName); |
return 11; |
} |
fgets(abCommandLine, sizeof(abCommandLine), fIn); |
fclose(fIn); |
} |
while (nMode == MODE_HEX_TO_DOT) { /* better if */ |
/* hex->dotted */ |
/*printf("Hex-In: %s\n", abCommandLine);*/ |
char *p = abCommandLine; |
char *q = p; |
unsigned char *pb = NULL; |
unsigned int nn = 0; |
#ifdef is_gmp |
mpz_t ll; |
mpz_init(ll); |
#else |
unsigned long ll = 0; |
#endif |
bool fOK = false; |
int fSub = 0; // Subtract value from next number output. Used when encoding {2 48} and up |
while (*p) { |
if (*p != '.' && *p != ':' && *p != '\r' && *p != '\n' && *p != '\x20' && *p != '\t') { |
*q++ = *p; |
} |
p++; |
} |
*q = '\0'; |
if (strlen(abCommandLine) % 2 != 0) { |
fprintf(stderr, "Encoded OID must have even number of hex digits!\n"); |
return 2; |
} |
if (strlen(abCommandLine) < 3) { |
fprintf(stderr, "Encoded OID must have at least three bytes!\n"); |
return 2; |
} |
nBinary = 0; |
p = abCommandLine; |
while (*p) { |
unsigned char b; |
// This allows also C-hexstring-notation |
if ((p[0] == '\\') && (p[1] == 'x')) { |
p += 2; |
continue; |
} |
// This allows also C-array-notation |
if ((p[0] == '0') && (p[1] == 'x')) { |
p += 2; |
continue; |
} |
if ((p[0] == ',') || (p[0] == '{') || (p[0] == '}') || (p[0] == ' ')) { |
p++; |
continue; |
} |
// Interpret upper nibble |
if (p[0] >= 'A' && p[0] <= 'F') { |
b = (p[0] - 'A' + 10) * 16; |
} else if (p[0] >= 'a' && p[0] <= 'f') { |
b = (p[0] - 'a' + 10) * 16; |
} else if (p[0] >= '0' && p[0] <= '9') { |
b = (p[0] - '0') * 16; |
} else { |
fprintf(stderr, "Must have hex digits only!\n"); |
return 2; |
} |
// Interpret lower nibble |
if (p[1] >= 'A' && p[1] <= 'F') { |
b += (p[1] - 'A' + 10); |
} else if (p[1] >= 'a' && p[1] <= 'f') { |
b += (p[1] - 'a' + 10); |
} else if (p[1] >= '0' && p[1] <= '9') { |
b += (p[1] - '0'); |
} else { |
fprintf(stderr, "Must have hex digits only!\n"); |
return 2; |
} |
if (nBinary+1 >= abb_size) { |
abb_size += ABB_EXPANSION_SIZE; |
abBinary = (unsigned char*) realloc(abBinary, abb_size); |
if (abBinary == NULL) { |
fprintf(stderr, "Memory reallocation failure!\n"); |
return EXIT_FAILURE; |
} |
} |
abBinary[nBinary++] = b; |
p += 2; |
} |
/*printf("Hex-In: %s\n", abCommandLine);*/ |
if (fOutName != NULL) { |
fOut = fopen(fOutName, "wt"); |
if (fOut == NULL) { |
fprintf(stderr, "Unable to open output file %s\n", fOutName); |
return 33; |
} |
} else { |
fOut = stdout; |
} |
pb = abBinary; |
nn = 0; |
#ifdef is_gmp |
mpz_init(ll); |
#else |
ll = 0; |
#endif |
fOK = false; |
fSub = 0; |
// 0 = Universal Class Identifier Tag (can be more than 1 byte, but not in our case) |
// 1 = Length part (may have more than 1 byte!) |
// 2 = First two arc encoding |
// 3 = Encoding of arc three and higher |
unsigned char part = 0; |
unsigned char lengthbyte_count = 0; |
unsigned char lengthbyte_pos = 0; |
bool lengthfinished = false; |
bool arcBeginning = true; |
bool firstWrittenArc = true; |
while (nn < nBinary) { |
if (part == 0) { // Class Tag |
// Leading octet |
// Bit 7 / Bit 6 = Universal (00), Application (01), Context (10), Private(11) |
// Bit 5 = Primitive (0), Constructed (1) |
// Bit 4..0 = 00000 .. 11110 => Tag 0..30, 11111 for Tag > 30 (following bytes with the highest bit as "more" bit) |
// --> We don't need to respect 11111 (class-tag encodes in more than 1 octet) |
// as we terminate when the tag is not of type OID or RELATEIVE-OID |
// See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson. |
// Class: 8. - 7. bit |
// 0 (00) = Universal |
// 1 (01) = Application |
// 2 (10) = Context |
// 3 (11) = Private |
unsigned char cl = ((*pb & 0xC0) >> 6) & 0x03; |
if (cl != 0) { |
fprintf(stderr, "\nError at type: The OID tags are only defined as UNIVERSAL class tags.\n"); |
fprintf(fOut, "\n"); |
return 6; |
} |
// Primitive/Constructed: 6. bit |
// 0 = Primitive |
// 1 = Constructed |
unsigned char pc = *pb & 0x20; |
if (pc != 0) { |
fprintf(stderr, "\nError at type: OIDs must be primitive, not constructed.\n"); |
fprintf(fOut, "\n"); |
return 6; |
} |
// Tag number: 5. - 1. bit |
unsigned char tag = *pb & 0x1F; |
if (tag == 0x0D) { |
isRelative = true; |
} else if (tag == 0x06) { |
isRelative = false; |
} else { |
fprintf(stderr, "\nError at type: The tag number is neither an absolute OID (0x06) nor a relative OID (0x0D).\n"); |
fprintf(fOut, "\n"); |
return 6; |
} |
// Output |
if (isRelative) { |
fprintf(fOut, "RELATIVE"); |
} else { |
fprintf(fOut, "ABSOLUTE"); |
} |
fprintf(fOut, " OID"); |
part++; |
} else if (part == 1) { // Length |
// Find out the length and save it into ll |
// [length] is encoded as follows: |
// 0x00 .. 0x7F = The actual length is in this byte, followed by [data]. |
// 0x80 + n = The length of [data] is spread over the following 'n' bytes. (0 < n < 0x7F) |
// 0x80 = "indefinite length" (only constructed form) -- Invalid |
// 0xFF = Reserved for further implementations -- Invalid |
// See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson. |
if (nn == 1) { // The first length byte |
lengthbyte_pos = 0; |
if ((*pb & 0x80) != 0) { |
// 0x80 + n => The length is spread over the following 'n' bytes |
lengthfinished = false; |
lengthbyte_count = *pb & 0x7F; |
if (lengthbyte_count == 0x00) { |
fprintf(stderr, "\nLength value 0x80 is invalid (\"indefinite length\") for primitive types.\n"); |
fprintf(fOut, "\n"); |
return 7; |
} else if (lengthbyte_count == 0x7F) { |
fprintf(stderr, "\nLength value 0xFF is reserved for further extensions.\n"); |
fprintf(fOut, "\n"); |
return 7; |
} |
fOK = false; |
} else { |
// 0x01 .. 0x7F => The actual length |
if (*pb == 0x00) { |
fprintf(stderr, "\nLength value 0x00 is invalid for an OID.\n"); |
fprintf(fOut, "\n"); |
return 7; |
} |
#ifdef is_gmp |
mpz_set_ui(ll, *pb); |
#else |
ll = *pb; |
#endif |
lengthfinished = true; |
lengthbyte_count = 0; |
fOK = true; |
} |
} else { |
if (lengthbyte_count > lengthbyte_pos) { |
#ifdef is_gmp |
mpz_mul_ui(ll, ll, 0x100); |
mpz_add_ui(ll, ll, *pb); |
#else |
ll *= 0x100; |
ll += *pb; |
#endif |
lengthbyte_pos++; |
} |
if (lengthbyte_count == lengthbyte_pos) { |
lengthfinished = true; |
fOK = true; |
} |
} |
if (lengthfinished) { // The length is now in ll |
#ifdef is_gmp |
if (mpz_cmp_ui(ll, nBinary - 2 - lengthbyte_count) != 0) { |
fprintf(fOut, "\n"); |
if (fOut != stdout) { |
fclose(fOut); |
} |
fprintf(stderr, "\nInvalid length (%d entered, but %s expected)\n", nBinary - 2, mpz_get_str(NULL, 10, ll)); |
return 3; |
} |
mpz_set_ui(ll, 0); // reset for later usage |
#else |
if (ll != nBinary - 2 - lengthbyte_count) { |
fprintf(fOut, "\n"); |
if (fOut != stdout) { |
fclose(fOut); |
} |
fprintf(stderr, "\nInvalid length (%d entered, but %d expected)\n", nBinary - 2, ll); |
return 3; |
} |
ll = 0; // reset for later usage |
#endif |
fOK = true; |
part++; |
if (isRelative) part++; // Goto step 3! |
} |
} else if (part == 2) { // First two arcs |
int first = *pb / 40; |
int second = *pb % 40; |
if (first > 2) { |
first = 2; |
fprintf(fOut, " %d", first); |
firstWrittenArc = false; |
arcBeginning = true; |
if ((*pb & 0x80) != 0) { |
// 2.48 and up => 2+ octets |
// Output in "part 3" |
if (arcBeginning && (*pb == 0x80)) { |
fprintf(fOut, "\n"); |
if (fOut != stdout) { |
fclose(fOut); |
} |
fprintf(stderr, "\nEncoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n"); |
return 4; |
} else { |
arcBeginning = false; |
} |
#ifdef is_gmp |
mpz_add_ui(ll, ll, (*pb & 0x7F)); |
#else |
ll += (*pb & 0x7F); |
#endif |
fSub = 80; |
fOK = false; |
} else { |
// 2.0 till 2.47 => 1 octet |
second = *pb - 80; |
fprintf(fOut, ".%d", second); |
arcBeginning = true; |
fOK = true; |
#ifdef is_gmp |
mpz_set_ui(ll, 0); |
#else |
ll = 0; |
#endif |
} |
} else { |
// 0.0 till 0.37 => 1 octet |
// 1.0 till 1.37 => 1 octet |
fprintf(fOut, " %d.%d", first, second); |
firstWrittenArc = false; |
arcBeginning = true; |
fOK = true; |
#ifdef is_gmp |
mpz_set_ui(ll, 0); |
#else |
ll = 0; |
#endif |
} |
part++; |
} else if (part == 3) { // Arc three and higher |
if ((*pb & 0x80) != 0) { |
if (arcBeginning && (*pb == 0x80)) { |
fprintf(fOut, "\n"); |
if (fOut != stdout) { |
fclose(fOut); |
} |
fprintf(stderr, "\nEncoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n"); |
return 4; |
} else { |
arcBeginning = false; |
} |
#ifdef is_gmp |
mpz_mul_ui(ll, ll, 0x80); |
mpz_add_ui(ll, ll, (*pb & 0x7F)); |
#else |
ll *= 0x80; |
ll += (*pb & 0x7F); |
#endif |
fOK = false; |
} else { |
fOK = true; |
#ifdef is_gmp |
mpz_mul_ui(ll, ll, 0x80); |
mpz_add_ui(ll, ll, *pb); |
mpz_sub_ui(ll, ll, fSub); |
if (firstWrittenArc) { |
fprintf(fOut, " %s", mpz_get_str(NULL, 10, ll)); |
firstWrittenArc = false; |
} else { |
fprintf(fOut, ".%s", mpz_get_str(NULL, 10, ll)); |
} |
// Happens only if 0x80 paddings are allowed |
// fOK = mpz_cmp_ui(ll, 0) >= 0; |
mpz_set_ui(ll, 0); |
#else |
ll *= 0x80; |
ll += *pb; |
ll -= fSub; |
if (firstWrittenArc) { |
fprintf(fOut, " %lu", ll); |
firstWrittenArc = false; |
} else { |
fprintf(fOut, ".%lu", ll); |
} |
// Happens only if 0x80 paddings are allowed |
// fOK = ll >= 0; |
ll = 0; |
#endif |
fSub = 0; |
arcBeginning = true; |
} |
} |
pb++; |
nn++; |
} |
if (!fOK) { |
fprintf(fOut, "\n"); |
if (fOut != stdout) { |
fclose(fOut); |
} |
fprintf(stderr, "\nEncoding error. The OID is not constructed properly.\n"); |
return 4; |
} else { |
fprintf(fOut, "\n"); |
} |
if (fOut != stdout) { |
fclose(fOut); |
} |
break; |
}; |
while (nMode == MODE_DOT_TO_HEX) { /* better if */ |
/* dotted->hex */ |
/* printf("OID %s\n", abCommandLine); */ |
char *p = abCommandLine; |
unsigned char cl = 0x00; |
char *q = NULL; |
int nPieces = 1; |
int n = 0; |
unsigned char b = 0; |
unsigned int nn = 0; |
#ifdef is_gmp |
mpz_t l; |
#else |
unsigned long l = 0; |
#endif |
bool isjoint = false; |
// Alternative call: ./oid RELATIVE.2.999 |
if (__STRNICMP_LOCAL(p, "ABSOLUTE.", 9) == 0) { |
isRelative = false; |
p+=9; |
} else if (__STRNICMP_LOCAL(p, "RELATIVE.", 9) == 0) { |
isRelative = true; |
p+=9; |
} else { |
// use the CLI option |
// isRelative = false; |
} |
cl = 0x00; // Class. Always UNIVERSAL (00) |
// Tag for Universal Class |
if (isRelative) { |
cl |= 0x0D; |
} else { |
cl |= 0x06; |
} |
/* if (__STRNICMP_LOCAL(p, "OID.", 4) == 0) { |
p+=4; |
} */ |
q = p; |
nPieces = 1; |
while (*p) { |
if (*p == '.') { |
nPieces++; |
} |
p++; |
} |
n = 0; |
b = 0; |
p = q; |
while (n < nPieces) { |
q = p; |
while (*p) { |
if (*p == '.') { |
break; |
} |
p++; |
} |
#ifdef is_gmp |
mpz_init(l); |
#else |
l = 0; |
#endif |
if (*p == '.') { |
*p = 0; |
#ifdef is_gmp |
mpz_set_str(l, q, 10); |
#else |
l = (unsigned long) atoi(q); |
#endif |
q = p+1; |
p = q; |
} else { |
#ifdef is_gmp |
mpz_set_str(l, q, 10); |
#else |
l = (unsigned long) atoi(q); |
#endif |
q = p; |
} |
/* Digit is in l. */ |
if ((!isRelative) && (n == 0)) { |
#ifdef is_gmp |
if (mpz_cmp_ui(l, 2) > 0) { |
#else |
if (l > 2) { |
#endif |
fprintf(stderr, "\nEncoding error. The top arc is limited to 0, 1 and 2.\n"); |
return 5; |
} |
#ifdef is_gmp |
b += 40 * mpz_get_ui(l); |
isjoint = mpz_cmp_ui(l, 2) == 0; |
#else |
b = 40 * ((unsigned char)l); |
isjoint = l == 2; |
#endif |
} else if ((!isRelative) && (n == 1)) { |
#ifdef is_gmp |
if ((!isjoint) && (mpz_cmp_ui(l, 39) > 0)) { |
#else |
if ((l > 39) && (!isjoint)) { |
#endif |
fprintf(stderr, "\nEncoding error. The second arc is limited to 0..39 for root arcs 0 and 1.\n"); |
return 5; |
} |
#ifdef is_gmp |
if (mpz_cmp_ui(l, 47) > 0) { |
mpz_add_ui(l, l, 80); |
MakeBase128(l, 1); |
} else { |
b += mpz_get_ui(l); |
if (nBinary+1 >= abb_size) { |
abb_size += ABB_EXPANSION_SIZE; |
abBinary = (unsigned char*) realloc(abBinary, abb_size); |
if (abBinary == NULL) { |
fprintf(stderr, "Memory reallocation failure!\n"); |
return EXIT_FAILURE; |
} |
} |
abBinary[nBinary++] = b; |
} |
#else |
if (l > 47) { |
l += 80; |
MakeBase128(l, 1); |
} else { |
b += ((unsigned char) l); |
if (nBinary+1 >= abb_size) { |
abb_size += ABB_EXPANSION_SIZE; |
abBinary = (unsigned char*) realloc(abBinary, abb_size); |
if (abBinary == NULL) { |
fprintf(stderr, "Memory reallocation failure!\n"); |
return EXIT_FAILURE; |
} |
} |
abBinary[nBinary++] = b; |
} |
#endif |
} else { |
MakeBase128(l, 1); |
} |
n++; |
} |
if ((!isRelative) && (n < 2)) { |
fprintf(stderr, "\nEncoding error. The minimum depth of an encodeable absolute OID is 2. (e.g. 2.999)\n"); |
return 5; |
} |
if (fOutName != NULL) { |
fOut = fopen(fOutName, "wt"); |
if (fOut == NULL) { |
fprintf(stderr, "Unable to open output file %s\n", fOutName); |
return 33; |
} |
} else { |
fOut = stdout; |
} |
// Write class-tag |
if (nCHex == 1) { |
fprintf(fOut, "{ 0x%02X, ", cl); |
} else if (nCHex == 2) { |
fprintf(fOut, "\"\\x%02X", cl); |
} else { |
fprintf(fOut, "%02X ", cl); |
} |
// Write length |
if (nBinary <= 0x7F) { |
if (nCHex == 1) { |
fprintf(fOut, "0x%02X, ", nBinary); |
} else if (nCHex == 2) { |
fprintf(fOut, "\\x%02X", nBinary); |
} else { |
fprintf(fOut, "%02X ", nBinary); |
} |
} else { |
unsigned int nBinaryWork; |
unsigned int lengthCount = 0; |
nBinaryWork = nBinary; |
do { |
lengthCount++; |
nBinaryWork /= 0x100; |
} while (nBinaryWork > 0); |
if (lengthCount >= 0x7F) { |
fprintf(stderr, "\nThe length cannot be encoded.\n"); |
return 8; |
} |
if (nCHex == 1) { |
fprintf(fOut, "0x%02X, ", 0x80 + lengthCount); |
} else if (nCHex == 2) { |
fprintf(fOut, "\\x%02X", 0x80 + lengthCount); |
} else { |
fprintf(fOut, "%02X ", 0x80 + lengthCount); |
} |
nBinaryWork = nBinary; |
do { |
if (nCHex == 1) { |
fprintf(fOut, "0x%02X, ", nBinaryWork & 0xFF); |
} else if (nCHex == 2) { |
fprintf(fOut, "\\x%02X", nBinaryWork & 0xFF); |
} else { |
fprintf(fOut, "%02X ", nBinaryWork & 0xFF); |
} |
nBinaryWork /= 0x100; |
} while (nBinaryWork > 0); |
} |
nn = 0; |
while (nn < nBinary) { |
unsigned char b = abBinary[nn++]; |
if (nn == nBinary) { |
if (nCHex == 1) { |
fprintf(fOut, "0x%02X }\n", b); |
} else if (nCHex == 2) { |
fprintf(fOut, "\\x%02X\"\n", b); |
} else { |
fprintf(fOut, "%02X\n", b); |
} |
} else { |
if (nCHex == 1) { |
fprintf(fOut, "0x%02X, ", b); |
} else if (nCHex == 2) { |
fprintf(fOut, "\\x%02X", b); |
} else { |
fprintf(fOut, "%02X ", b); |
} |
} |
} |
if (fOut != stdout) { |
fclose(fOut); |
} |
break; |
} |
free(abCommandLine); |
free(abBinary); |
return 0; |
} |
Property changes: |
Added: svn:mime-type |
+text/x-csrc |
\ No newline at end of property |
/trunk/c/test.sh |
---|
0,0 → 1,81 |
#!/bin/sh |
make |
# echo "-- test A" |
# ./oid -x "06 07 01 80 80 80 80 80 7F" |
# echo "-- test B" |
# ./oid -x "06 02 80 01" |
# echo "-- test C" |
# ./oid -x "06 02 80 7F" |
echo "-- 2.999"; |
./oid 2.999 |
echo "-- RELATIVE.2.999"; |
./oid RELATIVE.2.999 |
echo "-- 06 00" |
./oid -x "06 00"; |
echo "-- 06 80" |
./oid -x "06 80"; |
echo "-- 06 FF"; |
./oid -x "06 FF"; |
echo "-- 05 02 88 37" |
./oid -x "05 02 88 37"; |
echo "-- 06 02 88 37" |
./oid -x "06 02 88 37" |
echo "-- 0D 03 02 87 67" |
./oid -x "0D 03 02 87 67" |
exit |
echo "LONG OID" |
./oid -x "06 82 02 4C 88 37 82 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 7f" |
echo "-1.0 [NOT VALID]" |
./oid -1.0 |
echo "" |
echo "0.0" |
./oid 0.0 |
echo "" |
echo "0.39" |
./oid 0.39 |
echo "" |
echo "0.40 [NOT VALID]" |
./oid 0.40 |
echo "" |
echo "1.39" |
./oid 1.39 |
echo "" |
echo "1.40 [NOT VALID]" |
./oid 1.40 |
echo "" |
echo "3.0 [NOT VALID]" |
./oid 3.0 |
echo "" |
echo "2.999 == (06 02 88 37)"; |
./oid 2.999 |
echo "" |
echo "(06 01 27)" |
./oid -x "06 01 27" |
echo "(06 01 4F)" |
./oid -x "06 01 4F" |
echo "(06 01 7F)" |
./oid -x "06 01 7F" |
echo "(06 01 80) [NOT VALID]" |
./oid -x "06 01 80" |
echo "(06 02 88 37)" |
./oid -x "06 02 88 37" |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
Added: svn:mime-type |
+text/x-sh |
\ No newline at end of property |
/trunk/composer.json |
---|
0,0 → 1,22 |
{ |
"name": "danielmarschall/oidconverter", |
"description": "OID/DER converter", |
"version": "1.0", |
"type": "library", |
"homepage": "https://www.viathinksoft.com/projects/oidconverter", |
"authors": [ |
{ |
"name": "Daniel Marschall", |
"email": "info@daniel-marschall.de", |
"homepage": "https://www.daniel-marschall.de/" |
} |
], |
"license": [ |
"Apache-2.0" |
], |
"prefer-dist": true, |
"minimum-stability": "dev", |
"require": { |
"php": ">=7.0" |
} |
} |
/trunk/php/OidDerConverter.class.phps |
---|
0,0 → 1,380 |
<?php |
/* |
* OidDerConverter.class.php, Version 1.1.1; Based on version 1.3+viathinksoft11 of oid.c |
* Copyright 2014-2022 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
// Note: Leading zeros are permitted in dotted notation. |
// TODO: define output format as parameter; don't force the user to use hexStrToArray |
class OidDerConverter { |
/** |
* @arg $str "\x12\x23" or "12 34" |
* @return array(0x12, 0x23) |
*/ |
// Doesn't need to be public, but it is a nice handy function, especially in the testcases |
public static function hexStrToArray($str) { |
$out = array(); |
$str = str_replace('\x', '', $str); |
$str = trim($str); |
$str = str_replace(' ', '', $str); |
$ary = str_split($str, 2); |
foreach ($ary as &$a) { |
$a = hexdec($a); |
} |
return $ary; |
} |
/** |
* @return string|false Outputs .<oid> for an absolute OID and <oid> for a relative OID. |
*/ |
public static function derToOID($abBinary, $verbose=false) { |
$output_oid = array(); |
$output_absolute = true; |
if (count($abBinary) < 3) { |
if ($verbose) fprintf(STDERR, "Encoded OID must have at least three bytes!\n"); |
return false; |
} |
$nBinary = count($abBinary); |
$ll = gmp_init(0); |
$fOK = false; |
$fSub = 0; // Subtract value from next number output. Used when encoding {2 48} and up |
// 0 = Universal Class Identifier Tag (can be more than 1 byte, but not in our case) |
// 1 = Length part (may have more than 1 byte!) |
// 2 = First two arc encoding |
// 3 = Encoding of arc three and higher |
$part = 0; |
$lengthbyte_count = 0; |
$lengthbyte_pos = 0; |
$lengthfinished = false; |
$arcBeginning = true; |
$isRelative = null; // to avoid that phpstan complains |
foreach ($abBinary as $nn => &$pb) { |
if ($part == 0) { // Class Tag |
// Leading octet |
// Bit 7 / Bit 6 = Universal (00), Application (01), Context (10), Private(11) |
// Bit 5 = Primitive (0), Constructed (1) |
// Bit 4..0 = 00000 .. 11110 => Tag 0..30, 11111 for Tag > 30 (following bytes with the highest bit as "more" bit) |
// --> We don't need to respect 11111 (class-tag encodes in more than 1 octet) |
// as we terminate when the tag is not of type OID or RELATEIVE-OID |
// See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson. |
// Class: 8. - 7. bit |
// 0 (00) = Universal |
// 1 (01) = Application |
// 2 (10) = Context |
// 3 (11) = Private |
$cl = (($pb & 0xC0) >> 6) & 0x03; |
if ($cl != 0) { |
if ($verbose) fprintf(STDERR, "Error at type: The OID tags are only defined as UNIVERSAL class tags.\n"); |
return false; |
} |
// Primitive/Constructed: 6. bit |
// 0 = Primitive |
// 1 = Constructed |
$pc = $pb & 0x20; |
if ($pc != 0) { |
if ($verbose) fprintf(STDERR, "Error at type: OIDs must be primitive, not constructed.\n"); |
return false; |
} |
// Tag number: 5. - 1. bit |
$tag = $pb & 0x1F; |
if ($tag == 0x0D) { |
$isRelative = true; |
} else if ($tag == 0x06) { |
$isRelative = false; |
} else { |
if ($verbose) fprintf(STDERR, "Error at type: The tag number is neither an absolute OID (0x06) nor a relative OID (0x0D).\n"); |
return false; |
} |
// Output |
$output_absolute = !$isRelative; |
$part++; |
} else if ($part == 1) { // Length |
// Find out the length and save it into $ll |
// [length] is encoded as follows: |
// 0x00 .. 0x7F = The actual length is in this byte, followed by [data]. |
// 0x80 + n = The length of [data] is spread over the following 'n' bytes. (0 < n < 0x7F) |
// 0x80 = "indefinite length" (only constructed form) -- Invalid |
// 0xFF = Reserved for further implementations -- Invalid |
// See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson. |
if ($nn == 1) { // The first length byte |
$lengthbyte_pos = 0; |
if (($pb & 0x80) != 0) { |
// 0x80 + n => The length is spread over the following 'n' bytes |
$lengthfinished = false; |
$lengthbyte_count = $pb & 0x7F; |
if ($lengthbyte_count == 0x00) { |
if ($verbose) fprintf(STDERR, "Length value 0x80 is invalid (\"indefinite length\") for primitive types.\n"); |
return false; |
} else if ($lengthbyte_count == 0x7F) { |
if ($verbose) fprintf(STDERR, "Length value 0xFF is reserved for further extensions.\n"); |
return false; |
} |
$fOK = false; |
} else { |
// 0x01 .. 0x7F => The actual length |
if ($pb == 0x00) { |
if ($verbose) fprintf(STDERR, "Length value 0x00 is invalid for an OID.\n"); |
return false; |
} |
$ll = gmp_init($pb); |
$lengthfinished = true; |
$lengthbyte_count = 0; |
$fOK = true; |
} |
} else { |
if ($lengthbyte_count > $lengthbyte_pos) { |
$ll = gmp_mul($ll, 0x100); |
$ll = gmp_add($ll, $pb); |
$lengthbyte_pos++; |
} |
if ($lengthbyte_count == $lengthbyte_pos) { |
$lengthfinished = true; |
$fOK = true; |
} |
} |
if ($lengthfinished) { // The length is now in $ll |
if (gmp_cmp($ll, $nBinary - 2 - $lengthbyte_count) != 0) { |
if ($verbose) fprintf(STDERR, "Invalid length (%d entered, but %s expected)\n", $nBinary - 2, gmp_strval($ll, 10)); |
return false; |
} |
$ll = gmp_init(0); // reset for later usage |
$fOK = true; |
$part++; |
if ($isRelative) $part++; // Goto step 3! |
} |
} else if ($part == 2) { // First two arcs |
$first = floor($pb / 40); |
$second = $pb % 40; |
if ($first > 2) { |
$first = 2; |
$output_oid[] = $first; |
$arcBeginning = true; |
if (($pb & 0x80) != 0) { |
// 2.48 and up => 2+ octets |
// Output in "part 3" |
if ($pb == 0x80) { |
if ($verbose) fprintf(STDERR, "Encoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n"); |
return false; |
} else { |
$arcBeginning = false; |
} |
$ll = gmp_add($ll, ($pb & 0x7F)); |
$fSub = 80; |
$fOK = false; |
} else { |
// 2.0 till 2.47 => 1 octet |
$second = $pb - 80; |
$output_oid[] = $second; |
$arcBeginning = true; |
$fOK = true; |
$ll = gmp_init(0); |
} |
} else { |
// 0.0 till 0.37 => 1 octet |
// 1.0 till 1.37 => 1 octet |
$output_oid[] = $first; |
$output_oid[] = $second; |
$arcBeginning = true; |
$fOK = true; |
$ll = gmp_init(0); |
} |
$part++; |
} else if ($part == 3) { // Arc three and higher |
if (($pb & 0x80) != 0) { |
if ($arcBeginning && ($pb == 0x80)) { |
if ($verbose) fprintf(STDERR, "Encoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n"); |
return false; |
} else { |
$arcBeginning = false; |
} |
$ll = gmp_mul($ll, 0x80); |
$ll = gmp_add($ll, ($pb & 0x7F)); |
$fOK = false; |
} else { |
$fOK = true; |
$ll = gmp_mul($ll, 0x80); |
$ll = gmp_add($ll, $pb); |
$ll = gmp_sub($ll, $fSub); |
$output_oid[] = gmp_strval($ll, 10); |
// Happens only if 0x80 paddings are allowed |
// $fOK = gmp_cmp($ll, 0) >= 0; |
$ll = gmp_init(0); |
$fSub = 0; |
$arcBeginning = true; |
} |
} |
} |
if (!$fOK) { |
if ($verbose) fprintf(STDERR, "Encoding error. The OID is not constructed properly.\n"); |
return false; |
} |
return ($output_absolute ? '.' : '').implode('.', $output_oid); |
} |
// Doesn't need to be public, but it is a nice handy function, especially in the testcases |
public static function hexarrayToStr($ary, $nCHex=false) { |
$str = ''; |
if ($ary === false) return false; |
foreach ($ary as &$a) { |
if ($nCHex) { |
$str .= sprintf("\"\\x%02X", $a); |
} else { |
$str .= sprintf("%02X ", $a); |
} |
} |
return trim($str); |
} |
public static function oidToDER($oid, $isRelative=false, $verbose=false) { |
if ($oid[0] == '.') { // MIB notation |
$oid = substr($oid, 1); |
$isRelative = false; |
} |
$cl = 0x00; // Class. Always UNIVERSAL (00) |
// Tag for Universal Class |
if ($isRelative) { |
$cl |= 0x0D; |
} else { |
$cl |= 0x06; |
} |
$arcs = explode('.', $oid); |
$b = 0; |
$isjoint = false; |
$abBinary = array(); |
if ((!$isRelative) && (count($arcs) < 2)) { |
if ($verbose) fprintf(STDERR, "Encoding error. The minimum depth of an encodeable absolute OID is 2. (e.g. 2.999)\n"); |
return false; |
} |
foreach ($arcs as $n => &$arc) { |
if (!preg_match('@^\d+$@', $arc)) { |
if ($verbose) fprintf(STDERR, "Encoding error. Arc '%s' is invalid.\n", $arc); |
return false; |
} |
$l = gmp_init($arc, 10); |
if ((!$isRelative) && ($n == 0)) { |
if (gmp_cmp($l, 2) > 0) { |
if ($verbose) fprintf(STDERR, "Encoding error. The top arc is limited to 0, 1 and 2.\n"); |
return false; |
} |
$b += 40 * gmp_intval($l); |
$isjoint = gmp_cmp($l, 2) == 0; |
} else if ((!$isRelative) && ($n == 1)) { |
if ((!$isjoint) && (gmp_cmp($l, 39) > 0)) { |
if ($verbose) fprintf(STDERR, "Encoding error. The second arc is limited to 0..39 for root arcs 0 and 1.\n"); |
return false; |
} |
if (gmp_cmp($l, 47) > 0) { |
$l = gmp_add($l, 80); |
self::makeBase128($l, 1, $abBinary); |
} else { |
$b += gmp_intval($l); |
$abBinary[] = $b; |
} |
} else { |
self::makeBase128($l, 1, $abBinary); |
} |
} |
$output = array(); |
// Write class-tag |
$output[] = $cl; |
// Write length |
$nBinary = count($abBinary); |
if ($nBinary <= 0x7F) { |
$output[] = $nBinary; |
} else { |
$lengthCount = 0; |
$nBinaryWork = $nBinary; |
do { |
$lengthCount++; |
$nBinaryWork /= 0x100; |
} while ($nBinaryWork > 0); |
if ($lengthCount >= 0x7F) { |
if ($verbose) fprintf(STDERR, "The length cannot be encoded.\n"); |
return false; |
} |
$output[] = 0x80 + $lengthCount; |
$nBinaryWork = $nBinary; |
do { |
$output[] = $nBinaryWork & 0xFF; |
$nBinaryWork /= 0x100; |
} while ($nBinaryWork > 0); |
} |
foreach ($abBinary as $b) { |
$output[] = $b; |
} |
return $output; |
} |
protected static function makeBase128($l, $first, &$abBinary) { |
if (gmp_cmp($l, 127) > 0) { |
$l2 = gmp_div($l, 128); |
self::makeBase128($l2 , 0, $abBinary); |
} |
$l = gmp_mod($l, 128); |
if ($first) { |
$abBinary[] = gmp_intval($l); |
} else { |
$abBinary[] = 0x80 | gmp_intval($l); |
} |
} |
} |
/trunk/php/test.phps |
---|
0,0 → 1,34 |
<?php |
/* |
* tests.phps, Version 1.0; Based on version 1.11 of oid.c |
* Copyright 2014-2015 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
// TODO: more testcases |
error_reporting(E_ALL | E_NOTICE | E_DEPRECATED | E_STRICT); |
require_once __DIR__ . '/OidDerConverter.class.phps'; |
assert(OidDerConverter::hexarrayToStr(OidDerConverter::oidToDER('.2.999')) == '06 02 88 37'); |
assert(OidDerConverter::derToOID(array(0x06, 0x02, 0x88, 0x37)) == '.2.999'); |
assert(OidDerConverter::hexarrayToStr(OidDerConverter::oidToDER('2.999', true)) == '0D 03 02 87 67'); |
assert(OidDerConverter::derToOID(array(0x0D, 0x03, 0x02, 0x87, 0x67)) == '2.999'); |
assert(OidDerConverter::derToOID(OidDerConverter::hexstrToArray('0D 03 02 87 67')) == '2.999'); |
assert(OidDerConverter::derToOID(OidDerConverter::hexstrToArray('\x0D\x03\x02\x87\x67')) == '2.999'); |
/trunk/phpstan.neon.dist |
---|
0,0 → 1,17 |
parameters: |
level: 5 |
fileExtensions: |
- php |
- phps |
paths: |
- php |
excludePaths: |
analyseAndScan: |
- .phpstan.tmp |
tmpDir: .phpstan.tmp |
ignoreErrors: |
#- '#is always (true|false)\.#' |
#- '#Call to function assert\(\) with false will always evaluate to false\.#' |
#- '#with no typehint specified\.#' |
/trunk |
---|
Property changes: |
Added: svn:ignore |
+.phpstan.tmp |