41c7624bd5c12af9ac012ac8fbbcfe8aa7fddcd9
[libdcp.git] / src / crypt_chain.cc
1 /*
2     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program 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
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <fstream>
21 #include <sstream>
22 #include <boost/filesystem.hpp>
23 #include <boost/algorithm/string.hpp>
24 #include "crypt_chain.h"
25 #include "exceptions.h"
26
27 using std::string;
28 using std::ofstream;
29 using std::ifstream;
30 using std::stringstream;
31 using std::cout;
32
33 static void command (char const * c)
34 {
35         int const r = system (c);
36         if (WEXITSTATUS (r)) {
37                 stringstream s;
38                 s << "error in " << c << "\n";
39                 throw libdcp::MiscError (s.str());
40         }
41 }
42
43 void
44 libdcp::make_crypt_chain (boost::filesystem::path directory)
45 {
46         boost::filesystem::current_path (directory);
47         command ("openssl genrsa -out ca.key 2048");
48
49         {
50                 ofstream f ("ca.cnf");
51                 f << "[ req ]\n"
52                   << "distinguished_name = req_distinguished_name\n"
53                   << "x509_extensions   = v3_ca\n"
54                   << "[ v3_ca ]\n"
55                   << "basicConstraints = critical,CA:true,pathlen:3\n"
56                   << "keyUsage = keyCertSign,cRLSign\n"
57                   << "subjectKeyIdentifier = hash\n"
58                   << "authorityKeyIdentifier = keyid:always,issuer:always\n"
59                   << "[ req_distinguished_name ]\n"
60                   << "O = Unique organization name\n"
61                   << "OU = Organization unit\n"
62                   << "CN = Entity and dnQualifier\n";
63         }
64
65         command ("openssl rsa -outform PEM -pubout -in ca.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > ca_dnq");
66
67         string ca_dnq;
68
69         {
70                 ifstream f ("ca_dnq");
71                 getline (f, ca_dnq);
72                 /* XXX: is this right? */
73                 boost::replace_all (ca_dnq, "/", "\\\\/");
74         }
75         
76         string const ca_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.ROOT.NOT_FOR_PRODUCTION/dnQualifier=" + ca_dnq;
77
78         {
79                 stringstream c;
80                 c << "openssl req -new -x509 -sha256 -config ca.cnf -days 3650 -set_serial 5 -subj " << ca_subject << " -key ca.key -outform PEM -out ca.self-signed.pem";
81                 command (c.str().c_str());
82         }
83
84         command ("openssl genrsa -out intermediate.key 2048");
85
86         {
87                 ofstream f ("intermediate.cnf");
88                 f << "[ default ]\n"
89                   << "distinguished_name = req_distinguished_name\n"
90                   << "x509_extensions = v3_ca\n"
91                   << "[ v3_ca ]\n"
92                   << "basicConstraints = critical,CA:true,pathlen:2\n"
93                   << "keyUsage = keyCertSign,cRLSign\n"
94                   << "subjectKeyIdentifier = hash\n"
95                   << "authorityKeyIdentifier = keyid:always,issuer:always\n"
96                   << "[ req_distinguished_name ]\n"
97                   << "O = Unique organization name\n"
98                   << "OU = Organization unit\n"
99                   << "CN = Entity and dnQualifier\n";
100         }
101
102         command ("openssl rsa -outform PEM -pubout -in intermediate.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > inter_dnq");
103         
104         string inter_dnq;
105
106         {
107                 ifstream f ("inter_dnq");
108                 getline (f, inter_dnq);
109                 boost::replace_all (inter_dnq, "/", "\\\\/");
110         }
111                 
112         string const inter_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.INTERMEDIATE.NOT_FOR_PRODUCTION/dnQualifier=" + inter_dnq;
113
114         {
115                 stringstream s;
116                 s << "openssl req -new -config intermediate.cnf -days 3649 -subj " << inter_subject << " -key intermediate.key -out intermediate.csr";
117                 command (s.str().c_str());
118         }
119
120         
121         command ("openssl x509 -req -sha256 -days 3649 -CA ca.self-signed.pem -CAkey ca.key -set_serial 6 -in intermediate.csr -extfile intermediate.cnf -extensions v3_ca -out intermediate.signed.pem");
122
123         command ("openssl genrsa -out leaf.key 2048");
124
125         {
126                 ofstream f ("leaf.cnf");
127                 f << "[ default ]\n"
128                   << "distinguished_name = req_distinguished_name\n"
129                   << "x509_extensions   = v3_ca\n"
130                   << "[ v3_ca ]\n"
131                   << "basicConstraints = critical,CA:false\n"
132                   << "keyUsage = digitalSignature,keyEncipherment\n"
133                   << "subjectKeyIdentifier = hash\n"
134                   << "authorityKeyIdentifier = keyid,issuer:always\n"
135                   << "[ req_distinguished_name ]\n"
136                   << "O = Unique organization name\n"
137                   << "OU = Organization unit\n"
138                   << "CN = Entity and dnQualifier\n";
139         }
140
141         command ("openssl rsa -outform PEM -pubout -in leaf.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > leaf_dnq");
142         
143         string leaf_dnq;
144
145         {
146                 ifstream f ("leaf_dnq");
147                 getline (f, leaf_dnq);
148                 boost::replace_all (leaf_dnq, "/", "\\\\/");
149         }
150
151         string const leaf_subject = "/O=example.org/OU=example.org/CN=CS.smpte-430-2.LEAF.NOT_FOR_PRODUCTION/dnQualifier=" + leaf_dnq;
152
153         {
154                 stringstream s;
155                 s << "openssl req -new -config leaf.cnf -days 3648 -subj " << leaf_subject << " -key leaf.key -outform PEM -out leaf.csr";
156                 command (s.str().c_str());
157         }
158
159         command ("openssl x509 -req -sha256 -days 3648 -CA intermediate.signed.pem -CAkey intermediate.key -set_serial 7 -in leaf.csr -extfile leaf.cnf -extensions v3_ca -out leaf.signed.pem");
160 }