1/*
2 * Copyright (C) 2005 Justin Karneges <justin@affinix.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 */
19
20/* mozilla certdata converter. adapted from the debian ruby script */
21
22#include <QtCrypto>
23
24#include <QCoreApplication>
25#include <QFile>
26#include <QRegularExpression>
27#include <QTextStream>
28
29QStringList splitWithQuotes(const QString &in, char c);
30
31int main(int argc, char **argv)
32{
33 QCA::Initializer qcaInit;
34 QCoreApplication app(argc, argv);
35
36 if (argc < 3) {
37 printf(format: "usage: mozcerts [certdata.txt] [outfile.pem]\n");
38 return 0;
39 }
40
41 QFile infile(QString::fromLocal8Bit(ba: argv[1]));
42 if (!infile.open(flags: QFile::ReadOnly)) {
43 fprintf(stderr, format: "Error opening input file\n");
44 return 1;
45 }
46
47 QFile outfile(QString::fromLocal8Bit(ba: argv[2]));
48 if (!outfile.open(flags: QFile::WriteOnly | QFile::Truncate)) {
49 fprintf(stderr, format: "Error opening output file\n");
50 return 1;
51 }
52
53 int count = 0;
54 QString name;
55 QTextStream ts(&infile);
56 while (!ts.atEnd()) {
57 QString line = ts.readLine();
58 if (line.startsWith(c: QLatin1Char('#')))
59 continue;
60 line = line.trimmed();
61 if (line.isEmpty())
62 continue;
63
64 if (line.startsWith(s: QLatin1String("CKA_LABEL"))) {
65 const QStringList list = splitWithQuotes(in: line, c: ' ');
66 if (list.count() != 3)
67 continue;
68
69 name = list[2];
70 // make an output filename based on the name
71 // outname = name.replace(QRegExp("\\/"), "_")
72 // .replace(QRegExp("\\s+"), "_")
73 // .replace(QRegExp("[()]"), "=")
74 // .replace(QRegExp(","), "_") + ".pem";
75 continue;
76 } else if (line == QLatin1String("CKA_VALUE MULTILINE_OCTAL")) {
77 QByteArray buf;
78 while (!ts.atEnd()) {
79 line = ts.readLine().trimmed();
80 if (line == QLatin1String("END"))
81 break;
82 static const QRegularExpression rx(QStringLiteral("\\\\([0-3][0-7][0-7])"));
83 int pos = 0;
84 QRegularExpressionMatch match = rx.match(subject: line, offset: pos);
85 while (match.hasMatch()) {
86 QString str = match.captured(nth: 1);
87 uchar c = str.toInt(ok: nullptr, base: 8);
88 buf.append(c);
89 pos += match.capturedLength();
90 match = rx.match(subject: line, offset: pos);
91 }
92 }
93
94 printf(format: ">> [%s], %d bytes\n", qPrintable(name), int(buf.size()));
95
96 QTextStream ts(&outfile);
97 ts << "-----BEGIN CERTIFICATE-----" << '\n';
98 QCA::Base64 enc;
99 enc.setLineBreaksEnabled(true);
100 enc.setLineBreaksColumn(64);
101 ts << enc.arrayToString(a: buf) << '\n';
102 ts << "-----END CERTIFICATE-----" << '\n';
103
104 ++count;
105 }
106 }
107 printf(format: "Wrote %d certs to [%s]\n", count, argv[2]);
108
109 return 0;
110}
111
112int find_notchar(const QString &str, char c, int offset)
113{
114 for (int n = offset; n < str.length(); ++n) {
115 if (str[n] != QLatin1Char(c))
116 return n;
117 }
118 return -1;
119}
120
121QStringList splitWithQuotes(const QString &in, char c)
122{
123 QStringList result;
124 int at = 0;
125 if (in[at] == QLatin1Char(c))
126 at = find_notchar(str: in, c, offset: at);
127 while (at != -1) {
128 bool quote = false;
129 int end;
130 QString str;
131 if (in[at] == QLatin1Char('\"')) {
132 quote = true;
133 ++at;
134 end = in.indexOf(c: QLatin1Char('\"'), from: at);
135 if (end == -1)
136 break;
137 } else
138 end = in.indexOf(c: QLatin1Char(c), from: at);
139
140 if (end != -1)
141 str = in.mid(position: at, n: end - at);
142 else
143 str = in.mid(position: at);
144
145 if (!str.isEmpty())
146 result += str;
147
148 if (quote)
149 end = in.indexOf(c: QLatin1Char(c), from: end);
150
151 if (end != -1)
152 at = find_notchar(str: in, c, offset: end);
153 else
154 at = -1;
155 }
156 return result;
157}
158

source code of qca/tools/mozcerts/main.cpp